diff --git a/package-lock.json b/package-lock.json
index f43d2db..665e1fc 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -12,7 +12,7 @@
"@astrojs/svelte": "7.0.9",
"@fortawesome/free-brands-svg-icons": "6.7.2",
"@fortawesome/free-solid-svg-icons": "6.7.2",
- "@jsonquerylang/jsonquery": "4.1.1",
+ "@jsonquerylang/jsonquery": "5.0.0",
"astro": "5.5.6",
"fracturedjsonjs": "4.0.2",
"rehype-autolink-headings": "7.1.0",
@@ -1190,9 +1190,9 @@
}
},
"node_modules/@jsonquerylang/jsonquery": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/@jsonquerylang/jsonquery/-/jsonquery-4.1.1.tgz",
- "integrity": "sha512-Rfyvq70Zrb561BqSuXLsl0rG0/1tz913EQDL/4zpkp+laFGUxXIVPSaJWcdREJwADXLZDkQyaWplzEaPQvh+7A==",
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/@jsonquerylang/jsonquery/-/jsonquery-5.0.0.tgz",
+ "integrity": "sha512-RkC/sqdnsfTEP1LlagqTfem+GHDiTT1gwhO/WN7JUF96e61kyVKDIhvfnvmQsRJdHL40qVTtaGIk0Hg1R2Oj1w==",
"license": "ISC",
"bin": {
"jsonquery": "bin/cli.js"
diff --git a/package.json b/package.json
index 9431c20..2941357 100644
--- a/package.json
+++ b/package.json
@@ -16,7 +16,7 @@
"@astrojs/svelte": "7.0.9",
"@fortawesome/free-brands-svg-icons": "6.7.2",
"@fortawesome/free-solid-svg-icons": "6.7.2",
- "@jsonquerylang/jsonquery": "4.1.1",
+ "@jsonquerylang/jsonquery": "5.0.0",
"astro": "5.5.6",
"fracturedjsonjs": "4.0.2",
"rehype-autolink-headings": "7.1.0",
diff --git a/src/components/QuickReference.svelte b/src/components/QuickReference.svelte
index c9f22b4..22c7912 100644
--- a/src/components/QuickReference.svelte
+++ b/src/components/QuickReference.svelte
@@ -147,8 +147,8 @@ let selectedDoc: ReferenceDoc | undefined = $state()
font-size: var(--font-size-mono);
}
- pre code {
- background: none;
+ pre {
+ margin: 2px;
}
.quick-reference-button {
diff --git a/src/components/data/examples.ts b/src/components/data/examples.ts
index 08d76c1..28cae94 100644
--- a/src/components/data/examples.ts
+++ b/src/components/data/examples.ts
@@ -37,7 +37,7 @@ export const examples: Example[] = [
{
name: 'example 2',
input: input2,
- query: `filter((.city == "New York") and (.age > 30))\n`
+ query: `filter(.city == "New York" and .age > 30)\n`
},
{
name: 'example 3',
diff --git a/src/components/data/reference.json b/src/components/data/reference.json
index fe333cd..032296e 100644
--- a/src/components/data/reference.json
+++ b/src/components/data/reference.json
@@ -58,9 +58,9 @@
},
{
"name": "Operator",
- "syntax": "(left operator right)",
- "description": "JSON Query supports all basic operators. When composing multiple operators,\n it is necessary to use parentheses. Operators do not have precedence since\n parentheses are required.",
- "examples": ["(.age >= 18)", "(.age >= 18) and (.age <= 65))"],
+ "syntax": "left operator right",
+ "description": "JSON Query supports all basic operators. Operators must have both a left and right hand side. To override the default precedence, an operator can be wrapped in parentheses (...).",
+ "examples": [".age >= 18", "filter(.age >= 18 and .age <= 65)"],
"documentation": { "title": "Operators", "urlAnchor": "operators" },
"references": [
{ "title": "equal", "urlAnchor": "eq", "syntax": "a == b" },
diff --git a/src/content/documentation.md b/src/content/documentation.md
index 040d36a..7d6c33a 100644
--- a/src/content/documentation.md
+++ b/src/content/documentation.md
@@ -46,7 +46,7 @@ The following table gives an overview of the JSON query Text Format:
| Type | Syntax | Example |
|-------------------------|------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------|
| [Function](#functions) | `name(argument1, argument2, ...)` | `sort(.age, "asc")` |
-| [Operator](#operators) | `(left operator right)` | `filter(.age >= 18)` |
+| [Operator](#operators) | `left operator right` | `filter(.age >= 18)` |
| [Pipe](#pipes) | query1 | query2 | ... | sort(.age) | pick(.name, .age) |
| [Object](#objects) | `{ prop1: query1, prop2: query2, ... }` | `{ names: map(.name), total: sum() }` |
| [Array](#arrays) | `[ item1, item2, ... ]` | `[ "New York", "Atlanta" ]` |
@@ -94,16 +94,16 @@ See page [Function reference](/reference) for a detailed overview of all availab
### Operators
-JSON Query supports all basic operators. Operators must be wrapped in parentheses `(...)`, must have both a left and right hand side, and do not have precedence since parentheses are required. The syntax is:
+JSON Query supports all basic operators. Operators must have both a left and right hand side. To override the default precedence, an operator can be wrapped in parentheses `(...)`. The syntax is:
```text
-(left operator right)
+left operator right
```
The following example tests whether a property `age` is greater than or equal to `18`:
```text
-(.age >= 18)
+.age >= 18
```
Operators are for example used to specify filter conditions:
@@ -112,12 +112,27 @@ Operators are for example used to specify filter conditions:
filter(.age >= 18)
```
-When composing multiple operators, it is necessary to use parentheses:
+When using multiple operators, they will be evaluated according to their precedence (highest first):
```text
-filter((.age >= 18) and (.age <= 65))
+filter(.age >= 18 and .age <= 65)
```
+Note that some operators, like `and`, `or`, `+`, and `-`, support more than two values and are evaluated left-to-right, like `2 + 3 + 4`. Others, like `^` and `==`, do not support more than two values. If needed, it is always possible to use parenthesis, like `(2 ^ 3) ^ 4`.
+
+The operators have the following precedence, from highest to lowest:
+
+| Precedence | Associativity | Operators |
+|-----------------------------|---------------|--------------------------------------|
+| 8: exponentiation | n/a | `^` |
+| 7: multiplicative operators | left-to-right | `*`, `/`, `%` |
+| 6: additive operators | left-to-right | `+`, `-` |
+| 5: relational operators | n/a | `>`, `>=`, `<`, `<=`, `in`, `not in` |
+| 4: equality operators | n/a | `==`, `!=` |
+| 3: and | left-to-right | `and` |
+| 2: or | left-to-right | `or` |
+| 1: pipe | left-to-right | `\|` |
+
See page [Function reference](/reference) for a detailed overview of all available functions and operators.
### Pipes
diff --git a/src/content/reference.md b/src/content/reference.md
index 647c585..529ce02 100644
--- a/src/content/reference.md
+++ b/src/content/reference.md
@@ -173,7 +173,7 @@ jsonquery(data, 'filter((.age > 30) and (.address.city == "New York"))')
## sort
-Sort a list with objects or values.
+Sort a list with objects or values. The function first orders values by type: `boolean`, `number`, `string`, and other types. Strings are compared alphabetically and case-sensitive. Objects and arrays are not re-ordered.
```text
sort()
@@ -559,7 +559,7 @@ jsonquery(events, 'map(substring(.time, 0, 10))')
## uniq
-Create a copy of an array where all duplicates are removed.
+Create a copy of an array where all duplicates are removed. Values are compared using the `eq` operator, which does a deep strict equal comparison.
```text
uniq()
@@ -636,7 +636,7 @@ jsonquery("hello", 'size()') // 5
## sum
-Calculate the sum of all values in an array.
+Calculate the sum of all values in an array. The function return `0` in case of an empty array.
```text
sum()
@@ -651,7 +651,7 @@ jsonquery([2.4, 5.7], 'sum()') // 8.1
## min
-Return the minimum of the values in an array.
+Return the minimum of the values in an array. The function returns `null` in case of an empty array.
```text
min()
@@ -666,7 +666,7 @@ jsonquery([5, 7, 3], 'min()') // 3
## max
-Return the maximum of the values in an array.
+Return the maximum of the values in an array. The function returns `null` in case of an empty array.
```text
max()
@@ -681,7 +681,7 @@ jsonquery([5, 7, 3], 'max()') // 7
## prod
-Calculate the product of the values in an array.
+Calculate the product of the values in an array. The function throws an error in case of an empty array.
```text
prod()
@@ -696,7 +696,7 @@ jsonquery([2, 3, 2, 7, 1, 1], 'prod()') // 84
## average
-Calculate the average of the values in an array.
+Calculate the average of the values in an array. The function throws an error in case of an empty array.
```text
average()
@@ -711,7 +711,7 @@ jsonquery([2, 3, 2, 7, 1], 'average()') // 3
## eq (`==`)
-Test whether two values are strictly equal. This will consider a string `"2"` and a number `2` to be _not_ equal for example since their data type differs.
+Test whether two values are deep strict equal. This will consider a string `"2"` and a number `2` to be _not_ equal for example, since their data type differs. Objects and arrays are compared recursively, so `{"id":1,"name":"Joe"}` and `{"name":"Joe","id":1}` are deep equal for example.
```text
a == b
@@ -741,7 +741,8 @@ jsonquery({ a: 2 }, 'eq(.a, 2)') // true
## gt (`>`)
-Test whether `a` is greater than `b`.
+Test whether `a` is greater than `b`. The operator supports comparing two numbers, two strings, or two booleans. In case of unsupported data types or mixed data types, the function returns `false.
+
```text
a > b
@@ -765,7 +766,7 @@ jsonquery(data, 'filter(.age > 18)')
## gte (`>=`)
-Test whether `a` is greater than or equal to `b`.
+Test whether `a` is greater than or equal to `b`. The operator supports comparing two numbers, two strings, or two booleans. In case of unsupported data types or mixed data types, the function returns `false.
```text
a >= b
@@ -790,7 +791,7 @@ jsonquery(data, 'filter(.age >= 18)')
## lt (`<`)
-Test whether `a` is less than `b`.
+Test whether `a` is less than `b`. The operator supports comparing two numbers, two strings, or two booleans. In case of unsupported data types or mixed data types, the function returns `false.
```text
a < b
@@ -814,7 +815,7 @@ jsonquery(data, 'filter(.age < 18)')
## lte (`<=`)
-Test whether `a` is less than or equal to `b`.
+Test whether `a` is less than or equal to `b`. The operator supports comparing two numbers, two strings, or two booleans. In case of unsupported data types or mixed data types, the function returns `false.
```text
a <= b
@@ -839,7 +840,7 @@ jsonquery(data, 'filter(.age <= 18)')
## ne (`!=`)
-Test whether two values are not equal. This is the opposite of the strict equal function `eq`. Two values are considered unequal when their data type differs (for example one is a string and another is a number), or when the value itself is different. For example a string `"2"` and a number `2` are considered unequal, even though their mathematical value is equal.
+Test whether two values are not deep strict equal. This is the opposite of the strict equal function `eq`. Two values are considered unequal when their data type differs (for example one is a string and another is a number), or when the value itself is different. For example a string `"2"` and a number `2` are considered unequal, even though their mathematical value is equal. Objects and arrays are compared recursively, so `{"id":1,"name":"Joe"}` and `{"name":"Joe","id":1}` are deep equal for example.
```text
a != b
@@ -868,11 +869,13 @@ jsonquery({ a: 2 }, 'a != "2"') // true (since not strictly equal)
## and
-Test whether both values are truthy. A non-truthy value is any of `false`, `0`, `""`, `null`, or `undefined`.
+Test whether two or more values are truthy. A non-truthy value is any of `false`, `0`, `""`, `null`, or `undefined`. The function throws an error in case of zero arguments.
```text
a and b
+a and b and c and ...
and(a, b)
+and(a, b, c, ...)
```
Examples:
@@ -892,11 +895,13 @@ jsonquery(data, 'filter((.name == "Chris") and (.age == 16))')
## or
-Test whether one or both values are truthy. A non-truthy value is any of `false`, `0`, `""`, `null`, or `undefined`.
+Test whether at least one of the values is truthy. A non-truthy value is any of `false`, `0`, `""`, `null`, or `undefined`. The function throws an error in case of zero arguments.
```text
a or b
+a or b or c or ...
or(a, b)
+or(a, b, c, ...)
```
Examples:
@@ -997,7 +1002,7 @@ jsonquery(data, 'if(.kid.age >= .minAge, .messageOk, .messageFail)')
## in
-Test whether the search value is one of the values of the provided list.
+Test whether the search value is one of the values of the provided list. Values are compared using the `eq` operator, which does a deep strict equal comparison.
```text
searchValue in values
@@ -1022,7 +1027,7 @@ jsonquery(data, 'filter(.age in [16, 18])')
## not in
-Test whether the search value is _not_ one of the values of the provided list.
+Test whether the search value is _not_ one of the values of the provided list. Values are compared using the `eq` operator, which does a deep strict equal comparison.
```text
searchValue not in values
@@ -1155,7 +1160,7 @@ jsonquery(data, '.a / .b') // 3
## pow (`^`)
-Calculate the exponent. Returns the result of raising `a` to the power of `b`, like `a^b`
+Calculate the exponent. Returns the result of raising `a` to the power of `b`, like `a ^ b`. The `^` operator does not support more than two values, so if you need to calculate a chain of multiple exponents you'll have to use parenthesis, like `(a ^ b) ^ c`.
```text
a ^ b