JavaScript implementation of the JSONata query and transformation language.
npm install jsonata
In Node.js:
var jsonata = require("jsonata");
var data = {
example: [
{value: 4},
{value: 7},
{value: 13}
]
};
var expression = jsonata("$sum(example.value)");
var result = expression.evaluate(data); // returns 24In a browser:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JSONata test</title>
<script src="lib/jsonata.js"></script>
<script>
function greeting() {
var json = JSON.parse(document.getElementById('json').value);
var result = jsonata('"Hello, " & name').evaluate(json);
document.getElementById('greeting').innerHTML = result;
}
</script>
</head>
<body>
<textarea id="json">{ "name": "Wilbur" }</textarea>
<button onclick="greeting()">Click me</button>
<p id="greeting"></p>
</body>
</html>jsonata uses ES2015 features such as generators. For browsers lacking these features, lib/jsonata-es5.js is provided.
Parse a string str as a JSONata expression and return a compiled JSONata expression object.
var expression = jsonata("$sum(example.value)");If the expression is not valid JSONata, an Error is thrown containing information about the nature of the syntax error, for example:
{
code: "S0202",
stack: "...",
position: 16,
token: "}",
value: "]",
message: "Syntax error: expected ']' got '}'"
}
expression has three methods:
Run the compiled JSONata expression against object input and return the result as a new object.
var result = expression.evaluate({example: [{value: 4}, {value: 7}, {value: 13}]});input should be a JavaScript value such as would be returned from JSON.parse(). If input could not have been parsed from a JSON string (is circular, contains functions, ...), evaluate's behaviour is not defined. result is a new JavaScript value suitable for JSON.stringify()ing.
bindings, if present, contains variable names and values (including functions) to be bound:
jsonata("$a + $b()").evaluate({}, {a: 4, b: () => 78});
// returns 82expression.evaluate() may throw a run-time Error:
var expression = jsonata("$notafunction()"); // OK, valid JSONata
expression.evaluate({}); // ThrowsThe Error contains information about the nature of the run-time error, for example:
{
code: "T1006",
stack: "...",
position: 14,
token: "notafunction",
message: "Attempted to invoke a non-function"
}
If callback(err, value) is supplied, expression.evaluate() returns undefined, the expression is run asynchronously and the Error or result is passed to callback.
jsonata("7 + 12").evaluate({}, {}, (error, result) => {
if(error) {
console.error(error);
return;
}
console.log("Finished with", result);
});
console.log("Started");
// Prints "Started", then "Finished with 19"Permanently binds a value to a name in the expression, similar to how bindings worked above. Modifies expression in place and returns undefined. Useful in a JSONata expression factory.
var expression = jsonata("$a + $b()");
expression.assign("a", 4);
expression.assign("b", () => 1);
expression.evaluate({}); // 5Note that the bindings argument in the expression.evaluate() call clobbers these values:
expression.evaluate({}, {a: 109}); // 110Permanently binds a function to a name in the expression.
var expression = jsonata("$greet()");
expression.registerFunction("greet", () => "Hello world");
expression.evaluate({}); // "Hello world"You can do this using expression.assign or bindings in expression.evaluate, but expression.registerFunction allows you to specify a function signature. This is a terse string which tells JSONata the expected input argument types and return value type of the function. JSONata raises a run-time error if the actual input argument types do not match (the return value type is not checked yet).
var expression = jsonata("$add(61, 10005)");
expression.registerFunction("add", (a, b) => a + b, "<nn:n>");
expression.evaluate({}); // 10066Function signatures are specified like so:
A function signature is a string of the form <params:return>. params is a sequence of type symbols, each one representing an input argument's type. return is a single type symbol representing the return value type.
Type symbols work as follows:
Simple types:
b- Booleann- numbers- stringl-null
Complex types:
a- arrayo- objectf- function
Union types:
(sao)- string, array or object(o)- same asou- equivalent to(bnsl)i.e. Boolean, number, string ornullj- any JSON type. Equivalent to(bnsloa)i.e. Boolean, number, string,null, object or array, but not functionx- any type. Equivalent to(bnsloaf)
Parametrised types:
a<s>- array of stringsa<x>- array of values of any type
Some examples of signatures of built-in JSONata functions:
$counthas signature<a:n>; it accepts an array and returns a number.$appendhas signature<aa:a>; it accepts two arrays and returns an array.$sumhas signature<a<n>:n>; it accepts an array of numbers and returns a number.$reducehas signature<fa<j>:j>; it accepts a reducer functionfand ana<j>(array of JSON objects) and returns a JSON object.
Each type symbol may also have options applied.
+- one or more arguments of this type- E.g.
$ziphas signature<a+>; it accepts one array, or two arrays, or three arrays, or...
- E.g.
?- optional argument- E.g.
$joinhas signature<a<s>s?:s>; it accepts an array of strings and an optional joiner string which defaults to the empty string. It returns a string.
- E.g.
-- if this argument is missing, use the context value ("focus").- E.g.
$lengthhas signature<s-:n>; it can be called as$length(OrderID)(one argument) but equivalently asOrderID.$length().
- E.g.
- JSONata language documentation
- JSONata tech talk
See the CONTRIBUTING.md for details of how to contribute to this repo.
