If you have a Java String
with JSON pass it in as a variable to XPath and call parse-json
on the variable:
Processor processor = new Processor(true);
String[] jsonExamples = { "1", "true", "null", "\"string\"", "[1,2,3]", "{ \"prop\" : \"value\" }" };
XPathCompiler compiler = processor.newXPathCompiler();
compiler.declareVariable(new QName("json"));
XPathExecutable executable = compiler.compile("parse-json($json)");
XPathSelector selector = executable.load();
for (String json : jsonExamples) {
selector.setVariable(new QName("json"), new XdmAtomicValue(json));
XdmValue value = selector.evaluate();
System.out.println(value);
}
If you have a file with JSON pass its file name or in general URI as a variable to XPath and call json-doc
(https://www.w3.org/TR/xpath-functions/#func-json-doc) on the variable:
compiler = processor.newXPathCompiler();
compiler.declareVariable(new QName("json-uri"));
executable = compiler.compile("json-doc($json-uri)");
selector = executable.load();
selector.setVariable(new QName("json-uri"), new XdmAtomicValue("example1.json")); // pass in a relative (e.g. 'example.json' or 'subdir/example.json') or an absolute URI (e.g. 'file:///C:/dir/subdir/example.json' or 'http://example.com/example.json') here, not an OS specific file path
XdmValue value = selector.evaluate();
System.out.println(value);
Of course you can separate the steps and parse a string to an XdmValue or a file to an XdmValue and then pass it in later as a variable to another XPath evaluation.
So lets assume you have employees.json
containing
{
"employees": [
{
"name": "mike",
"department": "accounting",
"age": 34
},
{
"name": "sally",
"department": "sales",
"age": 24
}
]
}
then you can parse it with the second sample into an XdmValue value and use that further as a context item for an expression e.g
avg(?employees?*?age)
would compute the average age:
Processor processor = new Processor(true);
XPathCompiler compiler = processor.newXPathCompiler();
compiler.declareVariable(new QName("json-uri"));
XPathExecutable executable = compiler.compile("json-doc($json-uri)");
XPathSelector selector = executable.load();
selector.setVariable(new QName("json-uri"), new XdmAtomicValue("employees.json"));
XdmValue value = selector.evaluate();
System.out.println(value);
executable = compiler.compile("avg(?employees?*?age)");
selector = executable.load();
selector.setContextItem((XdmItem) value);
XdmItem result = selector.evaluateSingle();
System.out.println(result);
At https://xqueryfiddle.liberty-development.net/94hwphZ I have another sample processing JSON, it also computes the average of a value with an expression using the lookup operator ?
, first with ?Students
to select the Students
item of the context map, then with an asterisk ?*
on the returned array to get a sequence of all array items, finally with ?Grade
to select the Grade
value of each array item:
avg(?Students?*!(?Grade, 70)[1])
but with the additional requirement to select a default of 70
for those objects/maps that don't have a Grade
. The sample JSON is
{
"Class Name": "Science",
"Teacher\u0027s Name": "Jane",
"Semester": "2019-01-01",
"Students": [
{
"Name": "John",
"Grade": 94.3
},
{
"Name": "James",
"Grade": 81.0
},
{
"Name": "Julia",
"Grade": 91.9
},
{
"Name": "Jessica",
"Grade": 72.4
},
{
"Name": "Johnathan"
}
],
"Final": true
}
The fiddle supports XQuery 3.1 but like for XPath 3.1 the JSON is passed in as a variable and then parsed with parse-json
into an XDM item to serve as the context item for further evaluation.
To give some examples of more complex XPath 3.1 expressions against JSON I have taken the JSON sample from the path examples in https://github.com/json-path/JsonPath as the JSON input to parse-json
(if you have a string) or json-doc
if you have a URI to a file or even a HTTP(S) location and used it as the context item for some paths (evaluated in the fiddle as XQuery 3.1 but XPath 3.1 is a subset and I think I have restricted the samples to XPath 3.1:
The samples are at:
The file is
{
"store": {
"book": [
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
},
{
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{
"category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
},
"expensive": 10
}