The json
library provides predicates for parsing and generating data
in the JSON format based on the specification and standard found at:
- https://www.rfc-editor.org/rfc/rfc8259
- https://www.ecma-international.org/publications-and-standards/standards/ecma-404/
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
).
Open the ../../docs/library_index.html#json link in a web browser.
To load all entities in this library, load the loader.lgt
file:
| ?- logtalk_load(json(loader)).
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:
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 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 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.
Some tests, notably parse_simple_valid_files
and
roundtrip_hexadecimals
, fail on backends such as ECLiPSe and GNU
Prolog that don't support Unicode.