json_path
This library provides predicates for parsing, generating, and evaluating JSONPath queries for native Logtalk JSON terms.
It is based on RFC 9535:
Current implementation status
This implementation currently supports:
child segments
descendant segments
name selectors
wildcard selectors
index selectors, including negative indexes
slice selectors
filter selectors
existence tests
logical operators:
||,&&, and!comparisons using literals, singular queries, and supported function expressions
function expressions:
length(),count(),match(),search(), andvalue()local I-Regexp matching support for alternation, grouping, wildcard
., character classes, single-character escapes, and quantifiers (*,+,?,{m},{m,},{m,n})Unicode general-category escapes
\p{...}and\P{...}using backendunicode_property/2support when availableadditional local validation for malformed character classes and for unsafe explicit range quantifiers (nested explicit ranges and very large upper bounds/spans are rejected)
validation of index and slice integers against the RFC 9535 I-JSON exact-integer range
validation that queries supplied in
codes(...)representation contain only Unicode scalar valuesnormalized path reporting
Still pending:
the remaining RFC 9535 function-extension surface
API documentation
Open the ../../apis/library_index.html#json_path link in a web browser.
Loading
To load all entities in this library, load the loader.lgt file:
| ?- logtalk_load(json_path(loader)).
Testing
To test this library predicates, load the tester.lgt file:
| ?- logtalk_load(json_path(tester)).
Representation
The library defines the json_path(_Representation_) parametric
object where _Representation_ can be one of:
atom- member names and normalized paths are represented as atomschars- member names and normalized paths are represented aschars(List)codes- member names and normalized paths are represented ascodes(List)
When using the default json_path object, member names and normalized
paths are represented as atoms.
Examples
Parse and evaluate a query:
| ?- json_path::parse(atom('$.store.book[0].title'), Query),
json_path::evaluate(Query, {store-{book-[{title-'Sayings of the Century'}]}}, Values).
Query = json_path([child([name(store)]), child([name(book)]), child([index(0)]), child([name(title)])])
Values = ['Sayings of the Century']
yes
Filter books by price:
| ?- JSON = {store-{book-[{title-'Sayings', price-8.95}, {title-'Honour', price-12.99}]}},
json_path::query(atom('$.store.book[?@.price < 10].title'), JSON, Values).
JSON = {store-{book-[{title-'Sayings', price-8.95}, {title-'Honour', price-12.99}]}}
Values = ['Sayings']
yes
Return normalized paths for the selected nodes:
| ?- json_path::parse(atom('$..j'), Query),
json_path::paths(Query, {o-{j-1}, a-[[{j-4}]]}, Paths).
Paths = ['$[''o''][''j'']', '$[''a''][0][0][''j'']']
yes