json_get predicate

18 views
Skip to first unread message

Giuseppe Giubaldo

unread,
Jan 9, 2018, 4:44:55 AM1/9/18
to SWI-Prolog
Hi everybody, in need some help to create this json_get predicate.

The predicate json_get/3 can be defined as: json_get(JSON_obj, Fields, Result). which is true when Result is recoverable by following the chain of fields in Fields (a list) starting from JSON_obj. A field represented by N (with N a major number o equal to 0) corresponds to an index of a JSON array. As a special case you must handle this case json_get(JSON_obj, Field, Result).
where Field is a SWI Prolog's string.

example

?- json_parse('{"nome" : "Arthur", "cognome" : "Dent"}', O),
json_get(O, ["nome"], R).
O = json_obj([(”nome”, ”Arthur”), (”cognome”, ”Dent”)])
R = ”Arthur”

The idea is to navigate json_obj O and find the field that i need, but how?

Thanks

Carlo Capelli

unread,
Jan 9, 2018, 5:20:16 AM1/9/18
to Giuseppe Giubaldo, SWI-Prolog
Hi Giuseppe

Your example seems flawed to me, since it's mixing general and special case.
I would propose a 'defaulty' solution (be aware this practice is somewhat controversial):

json_get(json_obj(Pairs), K, V) :-

memberchk((K,V), Pairs).

json_get(Obj, Vs, Rs) :-

maplist(json_get(Obj), Vs, Rs).



first let's create an easily usable object:

?- J = json_obj([("nome", "Arthur"), ("cognome", "Dent")]).

J = json_obj([("nome", "Arthur"), ("cognome", "Dent")]).



now the special case yields an atomic literal


?- json_get($J, "nome", N).

N = "Arthur",

...


while a list request get a list literal

?- so:json_get($J, ["nome","cognome"], N).

N = ["Arthur", "Dent"],

...


HTH
Ciao, Carlo


--
You received this message because you are subscribed to the Google Groups "SWI-Prolog" group.
To unsubscribe from this group and stop receiving emails from it, send an email to swi-prolog+unsubscribe@googlegroups.com.
Visit this group at https://groups.google.com/group/swi-prolog.
For more options, visit https://groups.google.com/d/optout.

Jan Wielemaker

unread,
Jan 9, 2018, 7:41:50 AM1/9/18
to Carlo Capelli, Giuseppe Giubaldo, SWI-Prolog
On 09/01/18 11:20, Carlo Capelli wrote:
> Hi Giuseppe
>
> Your example seems flawed to me, since it's mixing general and special case.
> I would propose a 'defaulty' solution (be aware this practice is
> somewhat controversial):
>
> json_get(json_obj(Pairs), K, V) :-
>
> memberchk((K,V), Pairs).

(Name Value) may be common in functional languages, but in Prolog we
do things differently. The literal translation would be [Name,Value].
Prolog has both lists and terms though and a good rule of thumb is that
lists are there for if you do not know the number of elements and terms
if you do know. (K,V) satisfies the rules as it is a term ','(K,V). It
is really easy to mess up with the parenthesis though. The common
choice for anonymous pairs is Key-Value which is the term '.'(Key,Value)
and supported by library(pairs), keysort/2, etc.

> json_get(Obj, Vs, Rs) :-
>
> maplist(json_get(Obj), Vs, Rs).
>
>
>
> first let's create an easily usable object:
>
> ?- J = json_obj([("nome", "Arthur"), ("cognome", "Dent")]).
>
> J = json_obj([("nome", "Arthur"), ("cognome", "Dent")]).

The second choice is that you probably do not want strings for the
keys but atoms. These are more compact and faster to compare and
do not need quotes. For the value this is less obvious. Using
strings allow distinguishing the JSON constants true, false and
null.

Note that SWI-Prolog comes with read and write predicates for JSON.
They represent JSON objects as either json([name=value, ...]) or
a SWI-Prolog dict. The latter provides access to keys simply as
Dict.Key, e.g.

?- [library(http/json)].
true.

?- json_read_dict(user_input,Dict), Name = Dict.name.
|: {"name": "Bob", "age": 25}
Dict = _5540{age:25, name:"Bob"},
Name = "Bob".

Cheers --- Jan

>
>
>
> now the special case yields an atomic literal
>
>
> ?- json_get($J, "nome", N).
>
> N = "Arthur",
>
> ...
>
>
> while a list request get a list literal
>
> ?- so:json_get($J, ["nome","cognome"], N).
>
> N = ["Arthur", "Dent"],
>
> ...
>
>
> HTH
> Ciao, Carlo
>
>
> 2018-01-09 10:44 GMT+01:00 Giuseppe Giubaldo <giub...@gmail.com
> <mailto:giub...@gmail.com>>:
>
> Hi everybody, in need some help to create this json_get predicate.
>
> The predicate |json_get/3| can be defined as: |json_get(JSON_obj,
> Fields, Result).| which is true when |Result| is recoverable by
> following the chain of fields in |Fields| (a list) starting
> from |JSON_obj|. A field represented by |N| (with |N| a major number
> o equal to 0) corresponds to an index of a JSON array. As a special
> case you must handle this case json_get(JSON_obj, Field, Result).
> where Field is a SWI Prolog's string.
>
> example
>
> ?- json_parse('{"nome" : "Arthur", "cognome" : "Dent"}', O),
> json_get(O, ["nome"], R).
> O = json_obj([(”nome”, ”Arthur”), (”cognome”, ”Dent”)])
> R = ”Arthur”
>
> The idea is to navigate json_obj O and find the field that i need,
> but how?
>
> Thanks
>
> --
> You received this message because you are subscribed to the Google
> Groups "SWI-Prolog" group.
> To unsubscribe from this group and stop receiving emails from it,
> send an email to swi-prolog+...@googlegroups.com
> <mailto:swi-prolog+...@googlegroups.com>.
> <https://groups.google.com/group/swi-prolog>.
> For more options, visit https://groups.google.com/d/optout
> <https://groups.google.com/d/optout>.
>
>
> --
> You received this message because you are subscribed to the Google
> Groups "SWI-Prolog" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to swi-prolog+...@googlegroups.com
> <mailto:swi-prolog+...@googlegroups.com>.
Reply all
Reply to author
Forward
0 new messages