Building results
The output of an expression can have any shape. Array and object constructors use JSON syntax, with expressions wherever values (and object keys) go.
Arrays
Square brackets build an array of the values of the expressions inside them:
input: address.json
[Address.City, Other.`Alternative.Address`.City]
=> ["Winchester", "London"]
Unlike a sequence, an array built with [...] keeps its structure: it is neither flattened nor
unwrapped when it has a single item. As a path step, it builds one array per context item:
input: address.json
Email.address
=> ["fred.smith@my-work.com", "fsmith@my-work.com", "freddy@my-social.com", "frederic.smith@very-serious.com"]
input: address.json
Email.[address]
=> [
["fred.smith@my-work.com", "fsmith@my-work.com"],
["freddy@my-social.com", "frederic.smith@very-serious.com"]
]
An array constructor can also select several paths at once, as a more precise alternative to wildcards:
input: address.json
[Address, Other.`Alternative.Address`].City
=> ["Winchester", "London"]
Ranges
Inside an array constructor, from..to produces the integers from from to to, both
included. Both ends must be integers (error T2003, T2004), and a range can have at most
10 million items (D2014).
[1..5]
=> [1, 2, 3, 4, 5]
[1..3, 7..9]
=> [1, 2, 3, 7, 8, 9]
[1..5].($ * $)
=> [1, 4, 9, 16, 25]
input: address.json
[1..$count(Phone)].("Phone " & $)
=> ["Phone 1", "Phone 2", "Phone 3", "Phone 4"]
Objects
Braces build an object from key: value pairs. Keys are expressions that must evaluate to
strings (error T1003); values are any expressions. Fields whose value is nothing are left
out.
input: address.json
{"name": FirstName, "city": Address.City, "fax": Phone[type = 'fax'].number}
=> {"name": "Fred", "city": "Winchester"}
Where the constructor appears changes what it does:
-
After
.it is a map step and builds one object per item:input: address.json Phone.{type: number} => [ {"home": "0203 544 1234"}, {"office": "01962 001234"}, {"office": "01962 001235"}, {"mobile": "077 7700 1234"} ] -
Directly after a path (no
.) it groups the items into a single object. Values for the same key are collected together; see Grouping.input: address.json Phone{type: number} => { "home": "0203 544 1234", "office": ["01962 001234", "01962 001235"], "mobile": "077 7700 1234" }With
[], every group is an array, whatever its size:input: address.json Phone{type: number[]} => { "home": ["0203 544 1234"], "office": ["01962 001234", "01962 001235"], "mobile": ["077 7700 1234"] }
JSON literals
Values of every JSON type can be written as they are in JSON: strings (with JSON escapes, and
either quote character), numbers, true, false, null, arrays and objects. Because JSONata is
a superset of JSON, a JSON document makes a good template for the output.
input: invoice.json
{
"account": Account.`Account Name`,
"orders": Account.Order.{
"id": OrderID,
"total": $round($sum(Product.(Price * Quantity)), 2),
"items": $count(Product)
},
"currency": "EUR"
}
=> {
"account": "Firefly",
"orders": [
{"id": "order103", "total": 90.57, "items": 2},
{"id": "order104", "total": 245.79, "items": 2}
],
"currency": "EUR"
}