2016-10-26 4 views
1

私はPrologでシンプルなWebサービスを開発していて、ユーザーにJSON形式のデータで応答したいと考えていました。良い機能はreply_json_dict/1です。これは辞書をとり、よく書式設定されたJSON本体でHTTP応答で変換します。swi-prologで辞書を使用しています

私の問題は、レスポンス辞書自体を構築することがやや面倒であるということです。たとえば、データを返すと、データIDがありますが、データプロパティー(おそらくバインドされていない変数)があるかもしれません。私は簡単にアプローチを探しています...正常に動作するので、出力はPropsがバインドされているかどうかによって、{ "id" : "III" }または{ "id" : "III", "attributes" : "AAA" }ですが、

OutDict0 = _{ id : DataId }, 
(nonvar(Props) -> OutDict1 = OutDict0.put(_{ attributes : Props }) ; OutDict1 = OutDict0), 
reply_json_dict(OutDict1) 

:現時点では私は、次の操作を行います。主な理由は、より多くのオプションのキーと値のペアを追加する必要がある場合、私は以下のような複数の意味を持つようになるからです:

OutDict0 = _{ id : DataId }, 
(nonvar(Props) -> OutDict1 = OutDict0.put(_{ attributes : Props }) ; OutDict1 = OutDict0), 
(nonvar(Time) -> OutDict2 = OutDict1.put(_{ time : Time }) ; OutDict2 = OutDict1), 
(nonvar(UserName) -> OutDict3 = OutDict2.put(_{ userName : UserName }) ; OutDict3 = OutDict2), 
reply_json_dict(OutDict3) 

これは間違っているようです。もっと簡単な方法はありますか?

乾杯、 ヤツェク代わりに辞書をいじりの

答えて

1

多くの感謝のマットとボリスの提案!

dict_filter_vars(DictIn, DictOut) :- 
    findall(Key=Value, (get_dict(Key, DictIn, Value), nonvar(Value)), Pairs), 
    dict_create(DictOut, _, Pairs). 

その後、私はそのような単純な使用することができます:きれいに見える

DictWithVars = _{ id : DataId, attributes : Props, time : Time, userName : UserName }, 
dict_filter_vars(DictWithVars, DictOut), 
reply_json_dict(DictOut) 
+0

これらの入力であなたが解決したことは良いことです!まだ質問が残っています:あなたが必要なリストをすでに持っているときに、なぜディクテーションを作成するのですか? dictsはPrologの標準的な機能ではないため、dictを使用するたびにアプリケーションの移植性が低下することを考慮してください。 – mat

+0

良い点ですが、現時点での移植性についてはあまり心配していません。 dictについての良い点は、キーがユニークなので、JSONオブジェクトへのマッピングがより自然なことです。 JSON標準ではユニークではないキーが許可されていますが、多くのライブラリではそうではないため、ユニークなキーを使用する方がよいことに注意してください。 – Jacek

+0

'findall'の最初の引数に' Key = Value'の前後にかっこは必要ありません。 –

3

が、この場合、私の推薦は  JSONを発するように異なる述語を使用することです。

例えば、json_write/2を使用すると、ライブラリに必要なHTTP  のように、現在の出力でJSONを出力できます。

データフィールドのあなたの表現は共通Name(Value)オプション処理のためのHTTPライブラリ全体で使用される表記法であるとしますinclude/3を使用して

 
Fields0 = [attributes(Props),time(Time),userName(UserName)], 

、あなたの全体の例は次のようになります。

 
main :- 
     Fields0 = [id(DataId),attributes(Props),time(Time),userName(UserName)], 
     include(ground, Fields0, Fields), 
     json_write(current_output, json(Fields)). 

sinである個々の要素に適した値を差し込むことで、自分で試すことができますgleton変数を上記のスニペットに追加してください。

例えば、我々は(任意)使用することができます。

 
     Fields0 = [id(i9),attributes(_),time('12:00'),userName(_)], 

は降伏:

 
?- main. 
{"id":"i9", "time":"12:00"} 
true. 

をあなたが唯一適しのContent-Typeヘッダーを放出し、同じ出力それを持っている必要がありますreply_json_dict/1となります。

+1

、素晴らしい提案、おかげで私はあなたのアイデアの組み合わせになってしまいました。現時点では、私は辞書でちょっと立ち往生しています。私のコードをあなたのやり方でやり直すのにどれくらいの費用がかかります。乾杯、Jacek – Jacek

+2

素晴らしい!必要な変更はきわめて局所的であることに注意してください。残りのすべてのコードが辞書を使用していても、辞書の代わりにリスト*を作成するだけで、アウトラインの値を出力できます。 – mat

+1

@Jacekフィルタリングされたリストの辞書を 'dict_create(D、_、Fields)'で作成するか、リストの要素を 'D = D0.put(Fields)'で既存のdictに追加することができます。 –

2

リストを使用してdictに入る必要があるすべての値を表す場合は、1つの手順で実行できます。

?- Props = [a,b,c], get_time(Time), 
    D0 = _{id:001}, 
    include(ground, [props:Props,time:Time,user:UserName], Fs), 
    D = D0.put(Fs). 
D0 = _17726{id:1}, 
Fs = [props:[a, b, c], time:1477557597.205908], 
D = _17726{id:1, props:[a, b, c], time:1477557597.205908}. 

これは、include(ground)というマットの答えでアイデアを借りています。

関連する問題