【问题标题】:Convert plain JSON to SWI-Prolog Dict将纯 JSON 转换为 SWI-Prolog 字典
【发布时间】:2021-08-11 00:47:00
【问题描述】:

我在 SWI-Prolog 中有一个简单的规则,我想在 AWS Lambda 函数中实现它。

我将收到以下json 形式的事件:

{
  "key1": "value1",
  "key2": "value2",
  "key3": "value3"
}

我的问题是我只能从 atom-like 数组或 json 文件中读取,但不能以 compound 形式读取普通的 json

我想做的是这样的:

lambda_handler(Event, Context, Response) :-
    atom_json_dict(Event, Dict, []),
    my_simple_rule(Dict.key1, Dict.key2, Dict.key3),
    Response = '{"result": "yes"}'.

my_simple_rule 是一个根据传递的值返回真或假的条件。

到目前为止我尝试的方法不起作用,因为 SWI-Prolog 在使用 atom_json_term/3json_read/2,3json_read_dict/2,3 时需要 Stream 或 String。

我也尝试通过这种方式将 JSON 强制转换为字符串:

format(atom(A), "~w", {"key1": "value1", "key2": "value2", "key3":"value3"}).

期待这一点,以便我可以将其转换为Term(Prolog dict):

{"key1": "value1", "key2": "value2", "key3":"value3"}

但结果如下:

'{key1:value1,key2:value2,key3:value3}'

失败了。

有人知道我如何在 Prolog 中使用纯 JSON 吗?

【问题讨论】:

  • 我有点困惑,哪个谓词失败了? atom_json_dict?
  • 首先,确定 Event 参数所采用的形式。如果您在控制台中运行 SWI-Prolog,请将 write_canonical(Event) 放入 lambda_handler/3,然后发布您看到的文本
  • @CapelliC 是我认识的最好的人之一,可以帮助您使用 SWI-Prolog 解决现实世界的 JSON 问题。如果您想得到答案,那么我建议您帮助他解决他需要帮助您的任何事情。
  • 感谢您的回复。 @CapelliC,当我尝试使用 write_canonical(Event) 时,结果如下:{','(:("key1","value1"),','(:("key2","value2"),:("key3","value3")))}。我尝试直接在 Lambda 中运行它,但我无法在日志中看到打印。

标签: json prolog swi-prolog


【解决方案1】:

Event 它已经是一个结构化的术语,所以这里是一个“ad hoc”适配器。 假设我们有一个文件 j2d.pl 包含

:- module(j2d,
          [ j2d/2
          ]).

j2d(Event,Dict) :-
    Event={CommaSequence},
    l2d(CommaSequence,_{},Dict).

l2d((A,R),D,U) :- !, updd(A,D,V), l2d(R,V,U).
l2d(A,D,U) :- updd(A,D,U).

updd(K:V,D,U) :- atom_string(A,K), put_dict(A,D,V,U).

然后可以从 SWI-Prolog 控制台测试代码:

?- use_module(j2d).
true.

?- Event={
"key1": "value1",
"key2": "value2",
"key3": "value3"
}.
Event = {"key1":"value1", "key2":"value2", "key3":"value3"}.

?- j2d($Event,Dict).

Dict = _14542{key1:"value1", key2:"value2", key3:"value3"},
Event = {"key1":"value1", "key2":"value2", "key3":"value3"}.

不寻常的 $Event 语法是控制台的实用程序(也称为 REPL),它将变量 Event 替换为其最后一个值(也称为绑定)。

你的代码可能会变成

:- use_module(j2d).

lambda_handler(Event, Context, Response) :-
    j2d(Event,Dict),
    my_simple_rule(Dict.key1, Dict.key2, Dict.key3),
    Response = '{"result": "yes"}'.

【讨论】:

  • 谢谢,这在我的本地环境中有效,这正是我想要的。我仍然需要弄清楚如何在我的 Lambda 函数中使用它,因为 Event 变量仍然没有按预期工作,但这很有帮助。
【解决方案2】:

所以...我对 SWI-Prolog 如何处理 Lambda 中的事件 json 有误,所以我将在此处发布我的发现,以防有人遇到类似的挑战。

起初我以为事件json 是这样到达的:{"key1": 1, "key2": 2, "key3": 3}

但是,它看起来更像这样:json([key1=1, key2=2, key3=3]。这使得解析任务不同。

为了解决这个问题,我使用了以下代码,我希望它能够自我解释:

:- use_module(library(http/json)).
:- use_module(library(http/json_convert)).

% use this to test locally. If it works this way i should work in lambda:
handler(json([key1=10, key2=2, key3=3]), _, Response).


% Function handler
handler(json(Event), _, Response) :-

    json_to_prolog(json(Event), Json_term), % I transform the event json into a prolog term

    atom_json_term(A, Json_term, []), % I convert the JSON_term into an atom

    atom_json_dict(A, Dicty, []), % I convert the atom into a dict

    my_simple_function(Dicty.key1, Dicty.key2, Dicty.key3, Result), % Function evaluation

    json_to_prolog(json([result_key1="some_message", result_key2=Result]), Result_json), % Transform json term into actual json

    atom_json_term(Response, Result_json, []). % Transform json into atom so that lambda does not complain


my_simple_function(N1, N2, N3, Result) :-
    
    Result is N1 + N2 + N3.

所需的输入(您在 lambda 中的测试 json)将是:

{
  "key1": 1,
  "key2": 2,
  "key3": 3
}

虽然输出应如下所示:

{
  "result_key1": "some_message",
  "result_key2": 6
}

我希望这可以作为在 AWS 上使用 SWI-Prolog 的模板。

顺便说一句,我建议你看看这个repository 来为 Lambda 制作你的自定义 Prolog 运行时。

【讨论】:

    猜你喜欢
    • 2018-07-04
    • 2014-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多