json
The json
library provides predicates for parsing and generating data
in the JSON format based on the specification and standard found at:
It includes parametric objects whose parameters allow selecting the
representation for parsed JSON objects (curly
or list
), JSON
text strings (atom
, chars
, or codes
) and JSON pairs
(dash
, equal
, or colon
).
API documentation
Open the ../../docs/library_index.html#json link in a web browser.
Loading
To load all entities in this library, load the loader.lgt
file:
| ?- logtalk_load(json(loader)).
Testing
To test this library predicates, load the tester.lgt
file:
| ?- logtalk_load(json(tester)).
Some of the sample JSON test files are based on examples published at:
Representation
The following choices of syntax has been made to represent JSON elements as terms:
By default, JSON objects are represented using curly-bracketed terms,
{Pairs}
, where each pair uses the representationKey-Value
(see below for alternative representations).Arrays are represented using lists.
Text strings can be represented as atoms,
chars(List)
, orcodes(List)
. The default when decoding is to use atoms when using thejson
object. To decode text strings into lists of chars or codes, use thejson/1
with the parameter bound tochars
orcodes
. For example:| ?- json::parse(codes([34,104,101,108,108,111,34]), Term). Term = hello yes | ?- json(atom)::parse(codes([34,104,101,108,108,111,34]), Term). Term = hello yes | ?- json(chars)::parse(codes([34,104,101,108,108,111,34]), Term). Term = chars([h,e,l,l,o]) yes | ?- json(codes)::parse(codes([34,104,101,108,108,111,34]), Term). Term = codes([104,101,108,108,111]) yes
The JSON values
false
,true
andnull
are represented by, respectively, the@false
,@true
and@null
compound terms.
The following table exemplifies the term equivalents of JSON elements using default representations for objects, pairs, and strings:
JSON |
term |
---|---|
[1,2] |
[1,2] |
true |
@true |
false |
@false |
null |
@null |
-1 |
-1 |
[1.2345] |
[1.2345] |
[] |
[] |
[2147483647] |
[2147483647] |
[0] |
[0] |
[1234567890123456789] |
[1234567890123456789] |
[false] |
[@false] |
[-2147483648] |
[-2147483648] |
{“a”:null,”foo”:”bar”} |
{a-@null, foo-bar} |
[2.225073858507201e-308] |
[2.225073858507201e-308] |
[0,1] |
[0,1] |
[2.2250738585072014e-308] |
[2.2250738585072014e-308] |
[1.7976931348623157e+308] |
[1.7976931348623157e+308] |
[0.0] |
[0.0] |
[4294967295] |
[4294967295] |
[-1234567890123456789] |
[-1234567890123456789] |
[“foo”] |
[foo] |
[1] |
[1] |
[null] |
[@null] |
[-1.2345] |
[-1.2345] |
[5.0e-324] |
[5.0e-324] |
[-1] |
[-1] |
[true] |
[@true] |
[9223372036854775807] |
[9223372036854775807] |
For JSON objects that are two possible term representations:
JSON object |
term (curly) |
---|---|
{“a”:1, “b”:2, “c”:3} |
{a-1, b-2, c-3} |
{} |
{} |
and:
JSON object |
term (list) |
---|---|
{“a”:1, “b”:2, “c”:3} |
json([a-1, b-2, c-3]) |
{} |
json([]) |
For JSON pairs that are three possible representations:
JSON object |
term (dash) |
---|---|
{“a”:1, “b”:2, “c”:3} |
{a-1, b-2, c-3} |
and:
JSON object |
term (equal) |
---|---|
{“a”:1, “b”:2, “c”:3} |
{a=1, b=2, c=3} |
and:
JSON object |
term (colon) |
---|---|
{“a”:1, “b”:2, “c”:3} |
{a:1, b:2, c:3} |
By default, the curly-term representation and the dash pair
representation are used. The json/3
parametric object allows
selecting the desired representation choices. For example:
| ?- json(curly,dash,atom)::parse(atom('{"a":1, "b":2, "c":3}'), JSON).
JSON = {a-1, b-2, c-3}
yes
| ?- json(list,equal,atom)::parse(atom('{"a":1, "b":2, "c":3}'), JSON).
JSON = json([a=1, b=2, c=3])
yes
| ?- json(curly,colon,atom)::parse(atom('{"a":1, "b":2, "c":3}'), JSON).
JSON = {a:1, b:2, c:3}
yes
Encoding
Encoding is accomplished using the generate/2
predicate. For
example:
| ?- json::generate(codes(Encoding), [a,{b-c}]).
Encoding = [91,34,97,34,44,123,34,98,34,58,34,99,34,125,93]
yes
Alternatively:
| ?- json::generate(chars(Encoding), [a,{b-c}]).
Encoding = ['[','"',a,'"',',','{','"',b,'"',:,'"',c,'"','}',']']
Yes
| ?- json::generate(atom(Encoding), [a,{b-c}]).
Encoding = '["a",{"b":"c"}]'
Yes
Notice that generate/2
takes, as second argument, a Prolog term that
corresponds to the JSON Syntax in Prolog and produces the corresponding
JSON output in the format specified in the first argument:
(codes(Variable)
, stream(Stream)
, file(File)
,
chars(Variable)
or atom(Variable)
).
Decoding
Decoding is accomplished using the parse/2
predicate. For example,
to decode a given json file:
| ?- json::parse(file('simple/roundtrip_array_obj_array.json'), Term).
Term = [{a-[b]}]
yes
The parse/2
predicate first argument must indicate the input source
(codes(Codes)
, stream(Stream)
, line(Stream)
, file(Path)
,
chars(Chars)
or atom(Atom)
) containing a JSON payload to be
decoded into the Prolog term in the second argument.
Known issues
Some tests, notably parse_simple_valid_files
and
roundtrip_hexadecimals
, fail on backends such as ECLiPSe and GNU
Prolog that don’t support Unicode.