在 swi-prolog 中使用字典

using dictionaries in swi-prolog

我正在 Prolog 中开发一个简单的 Web 服务,并希望使用格式为 JSON 的数据来响应我的用户。 reply_json_dict/1 是一个不错的工具,它接受字典并将其转换为格式正确的 JSON 正文的 HTTP 响应。

我的麻烦是构建响应字典本身似乎有点麻烦。例如,当我 return 一些数据时,我有数据 ID 但 may/may 没有数据属性(可能是未绑定变量)。目前我执行以下操作:

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

效果很好,所以输出是 { "id" : "III" }{ "id" : "III", "attributes" : "AAA" } 取决于 Props 是否绑定,但是...我正在寻找更简单的方法。主要是因为如果我需要添加更多可选的 key/value 对,我最终会得到多重含义,例如:

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)

这似乎是错误的。有没有更简单的方法?

干杯, 亚采克

在这种情况下,我的建议是使用不同的谓词来发出JSON

,而不是乱用字典

例如,考虑 json_write/2,它允许您发出 JSON,也可以根据 HTTP 库的要求在当前输出上发出。

假设您对 数据字段的表示 是整个 HTTP 库中用于选项处理的通用 Name(Value) 表示法:

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

使用 include/3,您的整个示例变为:

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

您可以自己尝试一下,为上面代码段中的 单例变量 的各个元素插入合适的值。

例如,我们可以(任意)使用:

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

产量:

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

您只需要发出合适的 Content-Type header,并具有与 reply_json_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}.

这借用了 mat 的答案中的想法来使用 include(ground)

非常感谢 mat 和 Boris 的建议!我最终结合了你的想法:

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)