Skip to main content
Logic that reads text — matching what a customer wrote against a list, pulling a number out of a field, reading a tool result stored as a string — usually ends up in a Code step, which starts a sandbox before a single line runs. These functions keep it in an ordinary {{ ... }} expression, which evaluates in milliseconds.

Functions

Parsing JSON

$parseJson(text) reads JSON, and falls back to Python literal syntax — str() or pprint of a dict or list, with single quotes, True, False and None, laid out any way — which is how a voice transcript stores a tool’s result. $parseJson(text, false) reads JSON alone. Anything else is nothing (undefined), so pair it with $exists for a default:
A value that is already parsed — an object, array, number or boolean — comes back unchanged, so the same expression works whether an output was stored as text or as an object.
Do not use $eval to read data. $eval runs its argument as JSONata, so a string such as $$ inside a tool result or a customer message would be evaluated — and return everything the run holds. $parseJson only ever reads values.
A number on its own must be JSON: "-5" is -5, but text that Python alone reads as a number — "0x10", "1_000", "+5", "(5)" — is nothing, so an ID or a phone number is never mistaken for one. JSON allows numbers far larger than any value can hold, such as 1e400; text holding one reads as nothing too.

Parsing numbers

$number("n/a") is an error, and an error makes the whole expression evaluate to "". $parseNumber returns nothing instead, so one bad value does not take everything else with it:
Surrounding whitespace is ignored. Anything else around the digits ("£4", "1,000", "12 kg") makes the value not a number, so strip currency symbols and separators first, as above. Digits alone come back as an integer ("12" is 12); a decimal point or an exponent makes a decimal ("12." and "1e3" are 12.0 and 1000.0).

Regular expressions from data

A /literal/ is fixed when you write it. $regex builds one from a string, so the pattern can come from data — a list of names, a product code — and works anywhere a literal does: $match, $contains, $replace and $split. flags is any combination of: Escape every part that comes from data with $escapeRegex, or a value such as "1+1" or "(UK)" changes the pattern’s meaning:
Patterns use Python’s regular-expression syntax, so lookbehind ((?<!...)) and named groups work. A pattern counts toward the expression’s 10-second limit: one that backtracks without end — repetition inside repetition, like (a|aa)+$ against a long run of as that does not end the way it expects — fails its step at the deadline, except on the rare text described under Limits. Inside a JSONata string, a backslash starts an escape ('\b' is a backspace character), so write '\\b' for a regex word boundary.

Fuzzy matching

$similarity(a, b) is Python’s difflib.SequenceMatcher(None, a, b).ratio(): twice the number of characters the two strings have in common, in order, divided by their combined length. Case and accents count, so normalize both sides first when they should not:
Each string can be up to 10,000 characters.

Two standard functions

$sort and $lowercase behave as they do in JSONata itself:
  • $sort(array, comparator) is stable: elements the comparator does not separate keep their original order, so sorting by one key keeps an earlier order within each key.
  • $lowercase lowers case without folding it: "Straße" stays "straße".

Calling them on a path

Like JSONata’s own string functions, those that take text read it from the path when called without it: name.$unaccent() is $unaccent(name), and items.price.$parseNumber() reads every price. The same holds for $lowercase, $escapeRegex, $parseJson and $similarity (whose first string comes from the path).

Errors

A bad argument — an invalid pattern, an unknown flag, a number where text is expected — fails the way JSONata’s own functions do: the expression evaluates to "". Input that simply is not JSON or not a number is not an error; it is nothing, as described above.