JSON Expressions
Contents
Introduction
JSON-structured expressions provide an opportunity to filter and query API resources through composable operations.
Expressions are defined by the user through a simple domain-specific language. An expression will be evaluated with an API resource type as its input and may cross-reference properties within the given resource to produce a result.
Expression Format
Expressions are structured as a JSON object/tree describing operators and their operands, with any level of nesting. The structure resembles the composition of function calls in a typical programming language.
An operation consists of a single-property JSON object with an operator name as the property-key and a scalar operand or array of operands as the property value:
{ <operator> : <operand(s)> } => evaluated
Examples:
{ "toLower": "EXAMPLE" } => "example"
// Equivalent:
// toLower("EXAMPLE") => "example"Operations may include sub-operations within their operand(s). Each operand for an operation will be evaluated recursively before the operation itself is evaluated. Any JSON objects contained within an operand will be evaluated as nested operations.
Examples:
Ambiguity arises when a JSON object-literal or value containing object-literals is desired as an operand, without it being interpreted as a nested operation. For this purpose, a special value operator is provided which returns its operand(s) completely unevaluated.
Examples:
Supported Operators
Logical Operators
not
The not operator returns true if its operand evaluates to false. The operand must evaluate to a boolean.
Examples:
and
The and operator returns true if all of the values within the given array of operands evaluate to true. All operands must evaluate to booleans.
Examples:
or
The or operator returns true if any of the values within the given array of operands evaluate to true. All operands must evaluate to booleans.
Examples:
Relational Operators
equal
The equal operator returns true if all of the values within the given array of operands are equal according to a deep-equality check. All operands must evaluate to equivalent or compatible types.
Examples:
notEqual
The notEqual operator returns true if not all of the values within the given array of operands are equal according to a deep-equality check. All operands must evaluate to equivalent or compatible types.
Examples:
lessThan
The lessThan operator returns true if each of the values within the given array is less than its subsequent value. If 2 operands are provided, and both evaluate to dates, the operands will be compared as dates; otherwise, all operands must evaluate to numeric types.
The before operator is an alias for the lessThan operator.
Examples:
lessThanEqual
The lessThanEqual operator returns true if each of the values within the given array is less than or equal to its subsequent value. If 2 operands are provided, and both evaluate to dates, the operands will be compared as dates; otherwise, all operands must evaluate to numeric types.
Examples:
greaterThan
The greaterThan operator returns true if each of the values within the given array is greater than its subsequent value. If 2 operands are provided, and both evaluate to date types, the operands will be compared as dates; otherwise, all operands must evaluate to numeric types.
The after operator is an alias for the greaterThan operator.
Examples:
greaterThanEqual
The greaterThanEqual operator returns true if each of the values within the given array is greater than or equal to its subsequent value. If 2 operands are provided, and both evaluate to date types, the operands will be compared as dates; otherwise, all operands must evaluate to numeric types.
Examples:
String Operators
toLower
The toLower operator returns its operand to lower-case. The operand must evaluate to a string.
Examples:
toUpper
The toUpper operator returns its operand to upper-case. The operand must evaluate to a string.
Examples:
startsWith
The startsWith operator returns true if its first operand starts with its second operand. Both operands must evaluate to strings.
Examples:
endsWith
The endsWith operator returns true if its first operand ends with its second operand. Both operands must evaluate to strings.
Examples:
contains (also see Collection Operators)
The contains operator returns true if its first operand contains its second operand. If the first operand evaluates to an array, the array will be searched for the second operand. If the first operand evaluates to a string, the string will be searched for the second operand which must also evaluate to a string.
Examples:
split
The split operator returns an array of strings, formed by splitting its first operand on its second operand. Both operands must evaluate to strings.
Examples:
format
The format operator returns a formatted string. The first operand must evaluate to a format string and the second operand must evaluate to an array of parameters for the format string.
Example:
regexMatches
The regexMatches operator returns true if its second operand matches the pattern given by its first operand. Both operands must evaluate to strings, and the regex pattern must be ECMAScript-compatible.
Example:
parseJson
The parseJson operator returns its operand parsed into a JSON value. The operand must evaluate to a string.
Example:
Date Operators
date
The date operator converts its operand to a date object. The operand must evaluate to a string.
Example:
before
The before operator returns true if its first operand is before its second operand. Both operands must evaluate to date types. The date operator will need to be used to convert each operand, if dates are not automatically converted.
The before operator is an alias for the lessThan operator.
Examples:
after
The after operator returns true if its first operand is after its second operand. Both operands must evaluate to date types. The date operator will need to be used to convert each operand, if dates are not automatically converted.
The after operator is an alias for the greaterThan operator.
Examples:
addSeconds
The addSeconds operator returns a date-time value computed by adding its second operand as a number of seconds to its first operand. The first operand must evaluate to a date type. The date operator will need to be used to convert the first operand, if dates are not automatically converted.
Examples:
addMinutes
The addMinutes operator returns a date-time value computed by adding its second operand as a number of minutes to its first operand. The first operand must evaluate to a date type. The date operator will need to be used to convert the first operand, if dates are not automatically converted.
Examples:
addHours
The addHours operator returns a date-time value computed by adding its second operand as a number of hours to its first operand. The first operand must evaluate to a date type. The date operator will need to be used to convert the first operand, if dates are not automatically converted.
Examples:
addDays
The addDays operator returns a date-time value computed by adding its second operand as a number of days to its first operand. The first operand must evaluate to a date type. The date operator will need to be used to convert the first operand, if dates are not automatically converted.
Examples:
Arithmetic Operators
sum
The sum operator returns the sum of its operands, as a floating-point value. All operands must evaluate to or be convertible to numeric values.
The add operator is an alias for the sum operator.
Examples:
add
The add operator returns the sum of its operands, as a floating-point value. All operands must evaluate to or be convertible to numeric values.
The add operator is an alias for the sum operator.
Examples:
subtract
The subtract operator returns its second operand subtracted from its first operand, as a floating-point value. Both operands must evaluate to or be convertible to numeric values.
Examples:
Collection Operators
value
The value operator is used to "quote" object-literal values within a filter expression so they are not misinterpreted as operators during evaluation. The operand(s) will be returned unmodified and unevaluated.
Examples:
contains
The contains operator returns true if its first operand contains its second operand. If the first operand evaluates to an array, the array will be searched for the second operand. If the first operand evaluates to a string, the string will be searched for the second operand which must also evaluate to a string.
Examples:
overlaps
The overlaps operator returns true if its first operand overlaps/intersects with its second operand. Both operands must evaluate to arrays.
Examples:
groupBy
The groupBy operator returns an object containing grouped arrays of objects, using a path string to lookup the grouping property for each item in a given array. The first operand must evaluate to a path string and the second operand must evaluate to an array of objects to apply the groupings over. The property values used for grouping will be converted to strings for their grouping keys within the returned object.
Example:
Conditional Operators
ifElse
The ifElse operator returns its second operand if its first operand evaluates to true, otherwise its third operand is returned. The first operand must evaluate to a boolean. The ifElse operator is equivalent to a ternary conditional.
Examples:
Contextual Operators
path
The path operator returns a value within an implicit or given JSON object or array, using JSON-Path syntax for path lookups. If a single operand evaluating to a path string is provided, the path will be used to lookup a value within the resource associated with the current expression. If an array of operands is provided, the second operand should evaluate to an object or array which the first operand is a path into.
Examples:
with
The with operator binds values to names within a new evaluation context, evaluates its final operand under the prepared context, then finally unbinds the temporary evaluation context and returns the evaluated result. An array of operands must be provided where all leading operands are object-literal values and the final operand is any expression.
The with operator is special, in that its leading operands are received as object-literal values but are not interpreted as operations. Instead, the objects are interpreted as key-value bindings where each value is evaluated as an expression and assigned to its key/name within the current evaluation context. The final operand will be evaluated and returned.
Each with operation creates a nested evaluation context which inherits the bindings of its parent context. This is conceptually similar to lexical/block scoping. Leading operands will be evaluated in order; each leading operand will add bindings to the context and may reference values bound by prior operands or bound within parent contexts.
If a binding object contains multiple binding properties, the bindings in the object may not reference each other, but may reference pre-existing bindings.
The ref operator may be used to reference values which are bound within the current context or any parent context. The combination of the with and ref operators enables a sequential programming style and re-use of intermediate values. For complex expressions, this can be helpful for overall readability and terseness.
Examples:
ref
The ref operator references a named value bound within the current evaluation context. The operand must be a string-literal: the name of the referenced binding. If the same name has been bound multiple times within the current evaluation context, the most-recently bound value will be returned.
The with operator must be used to bind named values within an evaluation context before they may be referenced by the ref operator.
Examples:
Last updated
