|
| 1 | +--- |
| 2 | +id: version-2.1.0-embedding-extending |
| 3 | +title: Embedding and Extending JSONata |
| 4 | +sidebar_label: Embedding and Extending JSONata |
| 5 | +original_id: embedding-extending |
| 6 | +--- |
| 7 | + |
| 8 | +## API |
| 9 | + |
| 10 | +### jsonata(str) |
| 11 | + |
| 12 | +Parse a string `str` as a JSONata expression and return a compiled JSONata expression object. |
| 13 | + |
| 14 | +```javascript |
| 15 | +var expression = jsonata("$sum(example.value)"); |
| 16 | +``` |
| 17 | + |
| 18 | +If the expression is not valid JSONata, an `Error` is thrown containing information about the nature of the syntax error, for example: |
| 19 | + |
| 20 | +``` |
| 21 | +{ |
| 22 | + code: "S0202", |
| 23 | + stack: "...", |
| 24 | + position: 16, |
| 25 | + token: "}", |
| 26 | + value: "]", |
| 27 | + message: "Syntax error: expected ']' got '}'" |
| 28 | +} |
| 29 | +``` |
| 30 | + |
| 31 | +`expression` has three methods: |
| 32 | + |
| 33 | +### expression.evaluate(input[, bindings[, callback]]) |
| 34 | + |
| 35 | +Run the compiled JSONata expression against object `input` and return the result as a new object. |
| 36 | + |
| 37 | +```javascript |
| 38 | +var result = await expression.evaluate({example: [{value: 4}, {value: 7}, {value: 13}]}); |
| 39 | +``` |
| 40 | + |
| 41 | +`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. |
| 42 | + |
| 43 | +`bindings`, if present, contain variable names and values (including functions) to be bound: |
| 44 | + |
| 45 | +```javascript |
| 46 | +await jsonata("$a + $b()").evaluate({}, {a: 4, b: () => 78}); |
| 47 | +// returns 82 |
| 48 | +``` |
| 49 | + |
| 50 | +`expression.evaluate()` may throw a run-time `Error`: |
| 51 | + |
| 52 | +```javascript |
| 53 | +var expression = jsonata("$notafunction()"); // OK, valid JSONata |
| 54 | +await expression.evaluate({}); // Throws |
| 55 | +``` |
| 56 | + |
| 57 | +The `Error` contains information about the nature of the run-time error, for example: |
| 58 | + |
| 59 | +``` |
| 60 | +{ |
| 61 | + code: "T1006", |
| 62 | + stack: "...", |
| 63 | + position: 14, |
| 64 | + token: "notafunction", |
| 65 | + message: "Attempted to invoke a non-function" |
| 66 | +} |
| 67 | +``` |
| 68 | + |
| 69 | +If `callback(err, value)` is supplied, `expression.evaluate()` returns `undefined`, the expression is run asynchronously and the `Error` or result is passed to `callback`. |
| 70 | + |
| 71 | +```javascript |
| 72 | +await jsonata("7 + 12").evaluate({}, {}, (error, result) => { |
| 73 | + if(error) { |
| 74 | + console.error(error); |
| 75 | + return; |
| 76 | + } |
| 77 | + console.log("Finished with", result); |
| 78 | +}); |
| 79 | +console.log("Started"); |
| 80 | + |
| 81 | +// Prints "Started", then "Finished with 19" |
| 82 | +``` |
| 83 | + |
| 84 | +### expression.assign(name, value) |
| 85 | + |
| 86 | +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. |
| 87 | + |
| 88 | +```javascript |
| 89 | +var expression = jsonata("$a + $b()"); |
| 90 | +expression.assign("a", 4); |
| 91 | +expression.assign("b", () => 1); |
| 92 | + |
| 93 | +await expression.evaluate({}); // 5 |
| 94 | +``` |
| 95 | + |
| 96 | +Note that the `bindings` argument in the `expression.evaluate()` call clobbers these values: |
| 97 | + |
| 98 | +```javascript |
| 99 | +await expression.evaluate({}, {a: 109}); // 110 |
| 100 | +``` |
| 101 | + |
| 102 | +### expression.registerFunction(name, implementation[, signature]) |
| 103 | + |
| 104 | +Permanently binds a function to a name in the expression. |
| 105 | + |
| 106 | +```javascript |
| 107 | +var expression = jsonata("$greet()"); |
| 108 | +expression.registerFunction("greet", () => "Hello world"); |
| 109 | + |
| 110 | +await expression.evaluate({}); // "Hello world" |
| 111 | +``` |
| 112 | + |
| 113 | +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). |
| 114 | + |
| 115 | +```javascript |
| 116 | +var expression = jsonata("$add(61, 10005)"); |
| 117 | +expression.registerFunction("add", (a, b) => a + b, "<nn:n>"); |
| 118 | + |
| 119 | +await expression.evaluate({}); // 10066 |
| 120 | +``` |
| 121 | + |
| 122 | +### Function signature syntax |
| 123 | + |
| 124 | +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. |
| 125 | + |
| 126 | +Type symbols work as follows: |
| 127 | + |
| 128 | +Simple types: |
| 129 | + |
| 130 | +- `b` - Boolean |
| 131 | +- `n` - number |
| 132 | +- `s` - string |
| 133 | +- `l` - `null` |
| 134 | + |
| 135 | +Complex types: |
| 136 | + |
| 137 | +- `a` - array |
| 138 | +- `o` - object |
| 139 | +- `f` - function |
| 140 | + |
| 141 | +Union types: |
| 142 | + |
| 143 | +- `(sao)` - string, array or object |
| 144 | +- `(o)` - same as `o` |
| 145 | +- `u` - equivalent to `(bnsl)` i.e. Boolean, number, string or `null` |
| 146 | +- `j` - any JSON type. Equivalent to `(bnsloa)` i.e. Boolean, number, string, `null`, object or array, but not function |
| 147 | +- `x` - any type. Equivalent to `(bnsloaf)` |
| 148 | + |
| 149 | +Parametrised types: |
| 150 | + |
| 151 | +- `a<s>` - array of strings |
| 152 | +- `a<x>` - array of values of any type |
| 153 | + |
| 154 | +Some examples of signatures of built-in JSONata functions: |
| 155 | + |
| 156 | +- `$count` has signature `<a:n>`; it accepts an array and returns a number. |
| 157 | +- `$append` has signature `<aa:a>`; it accepts two arrays and returns an array. |
| 158 | +- `$sum` has signature `<a<n>:n>`; it accepts an array of numbers and returns a number. |
| 159 | +- `$reduce` has signature `<fa<j>:j>`; it accepts a reducer function `f` and an `a<j>` (array of JSON objects) and returns a JSON object. |
| 160 | + |
| 161 | +Each type symbol may also have *options* applied. |
| 162 | + |
| 163 | +- `+` - one or more arguments of this type |
| 164 | + - E.g. `$zip` has signature `<a+>`; it accepts one array, or two arrays, or three arrays, or... |
| 165 | +- `?` - optional argument |
| 166 | + - E.g. `$join` has 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. |
| 167 | +- `-` - if this argument is missing, use the context value ("focus"). |
| 168 | + - E.g. `$length` has signature `<s-:n>`; it can be called as `$length(OrderID)` (one argument) but equivalently as `OrderID.$length()`. |
| 169 | + |
| 170 | +### Writing higher-order function extensions |
| 171 | + |
| 172 | +It is possible to write an extension function that takes one or more functions in its list of arguments and/or returns |
| 173 | + a function as its return value. |
| 174 | + |
| 175 | + |
0 commit comments