JSON Values
JsonValue is Nexigon’s free-form JSON value type. It can be any JSON value: object, array, string, number, boolean, or null. Device properties, command inputs and outputs, metadata, and other API fields use it when they need arbitrary JSON.
The public json Sidex schema defines JsonValue together with generic tools for evaluating, selecting, comparing, and changing JSON values:
JsonValue: any JSON value.JsonExpr: an expression that evaluates to a JSON value.JsonPath: a path into another JSON value.JsonMutation: a declarative transformation applied to a JSON value.
Expressions
Every JSON expression evaluates to a JSON value. Predicate expressions are ordinary expressions whose final value must be JSON true or false.
Evaluation receives a caller-provided context of named JSON values. For instance, in operations, device properties are exposed as named values, so this expression reads the current value of the device property dev.nexigon.ota.current:
{
"kind": "NamedValue",
"name": "dev.nexigon.ota.current"
}
Named value identifiers must be 1 to 256 characters, start with a letter or digit, and contain only letters, digits, dots, underscores, or hyphens.
Expression Format
Expression objects are tagged with kind:
{ "kind": "Literal", "value": true }
Variants whose payload is a record inline that record’s fields. Variants whose payload is a raw JSON value or another expression use a payload-specific field such as value or expr.
Defaults And Missing Values
Missing named values and missing paths are evaluation errors by default. They are not treated as false or null.
NamedValue and Get can include default to recover from missing values:
{
"kind": "NamedValue",
"name": "com.example.optional",
"default": { "kind": "Literal", "value": null }
}
For Get, the default expression applies when the input expression is missing or when the path is missing. Other errors, such as traversing a scalar value as if it were an object, still fail evaluation. Default expressions are evaluated only when needed; if a default expression itself fails, that error is reported.
Expression Kinds
| Kind | Fields | Result |
|---|---|---|
Literal | value | Returns the constant JSON value in value. |
Current | none | Returns the value currently being mutated. Valid only inside a mutation expression. |
NamedValue | name, optional default | Reads a named JSON value from the evaluation context. |
Get | expr, path, optional default | Gets a nested value from the result of another expression. |
Exists | expr, path | Returns whether a path resolves against the result of expr. |
Equals | left, right | Returns whether two JSON values are equal. |
NotEquals | left, right | Returns whether two JSON values are not equal. |
LessThan | left, right | Ordered comparison over JSON numbers or strings. |
LessThanOrEquals | left, right | Ordered comparison over JSON numbers or strings. |
GreaterThan | left, right | Ordered comparison over JSON numbers or strings. |
GreaterThanOrEquals | left, right | Ordered comparison over JSON numbers or strings. |
In | left, right | Returns whether left appears in the JSON array produced by right. |
And | exprs | Short-circuiting conjunction over one or more expressions that must evaluate to booleans. |
Or | exprs | Short-circuiting disjunction over one or more expressions that must evaluate to booleans. |
Not | expr | Boolean negation over an expression that must evaluate to a boolean. |
VersionRequirement | expr, requirement | Evaluates expr as a version string and matches it against a version requirement. |
Boolean operators short-circuit. And stops at the first false result, and Or stops at the first true result. Operation definitions require at least one operand.
Exists is the explicit way to ask whether a path is present:
{
"kind": "Exists",
"expr": {
"kind": "NamedValue",
"name": "dev.nexigon.ota.current"
},
"path": ["version"]
}
If the input expression itself is missing, Exists evaluates to false. A non-empty path against a scalar value also evaluates to false; the empty path evaluates to true for any resolved JSON value.
Predicate Examples
Match a device property exactly:
{
"kind": "Equals",
"left": {
"kind": "NamedValue",
"name": "com.example.rollout.ring"
},
"right": { "kind": "Literal", "value": "stable" }
}
Match a nested field in a JSON property:
{
"kind": "Equals",
"left": {
"kind": "Get",
"expr": {
"kind": "NamedValue",
"name": "dev.nexigon.ota.status"
},
"path": ["state"]
},
"right": { "kind": "Literal", "value": "completed" }
}
Match when a version is absent or different:
{
"kind": "Or",
"exprs": [
{
"kind": "Not",
"expr": {
"kind": "Exists",
"expr": {
"kind": "NamedValue",
"name": "dev.nexigon.ota.current"
},
"path": ["version"]
}
},
{
"kind": "NotEquals",
"left": {
"kind": "Get",
"expr": {
"kind": "NamedValue",
"name": "dev.nexigon.ota.current"
},
"path": ["version"]
},
"right": { "kind": "Literal", "value": "2.0.0" }
}
]
}
Match a semantic version range:
{
"kind": "VersionRequirement",
"expr": {
"kind": "NamedValue",
"name": "dev.nexigon.agent.version"
},
"requirement": ">=1.8.0, <2.0.0"
}
Paths
Paths describe how to locate a value inside another JSON value. JsonPath is a JSON array of path segments.
String segments address object members. Non-negative integer segments address array elements and are represented as u32 in the Sidex schema. The empty path [] addresses the current value itself:
["firmware", "version"]
["items", 0, "id"]
A numeric string and a numeric segment are different: "0" addresses an object member named 0, while 0 addresses the first array element. Object member keys may be at most 256 characters.
Get Example
Use Get to read nested values:
{
"kind": "Get",
"expr": {
"kind": "NamedValue",
"name": "dev.nexigon.ota.status"
},
"path": ["state"]
}
Use default when a missing input expression or missing path should produce a fallback value:
{
"kind": "Get",
"expr": {
"kind": "NamedValue",
"name": "dev.nexigon.ota.status"
},
"path": ["progress"],
"default": { "kind": "Literal", "value": 0 }
}
Mutations
JSON mutations describe how to transform a current JSON value. Like expressions, mutations are evaluated in a caller-provided context.
Mutation Format
Mutation objects are tagged with mutation:
{
"mutation": "Set",
"path": [],
"expr": { "kind": "Literal", "value": true }
}
Mutation Kinds
| Mutation | Fields | Effect |
|---|---|---|
Set | path, expr | Replaces the value at path with the expression result. An empty path replaces the root value. |
MergePatch | path, expr | Evaluates expr and applies it as an RFC 7396 JSON Merge Patch to the value at path. An empty path patches the root value. |
Remove | path | Removes the value at path. Missing values are ignored. |
Path Mutation Behavior
Path-targeted Set and MergePatch can create missing object parents. Array indexes must already exist. Remove ignores missing values, but it still fails when the path tries to traverse through a value of the wrong type.
An empty path targets the root for Set and MergePatch. Remove requires a non-empty path; use the operation’s RemoveDeviceProperty step to delete an entire property.
Examples
Replace a whole value:
{
"mutation": "Set",
"path": [],
"expr": {
"kind": "Literal",
"value": { "version": "2.0.0" }
}
}
Apply a merge patch:
{
"mutation": "MergePatch",
"path": [],
"expr": {
"kind": "Literal",
"value": {
"version": "2.1.0",
"metadata": { "ring": "stable" }
}
}
}
Set one value at a path:
{
"mutation": "Set",
"path": ["features", "ota"],
"expr": { "kind": "Literal", "value": true }
}
Apply a merge patch to one value at a path:
{
"mutation": "MergePatch",
"path": ["metadata"],
"expr": { "kind": "Literal", "value": { "ring": "stable" } }
}
Remove one value at a path:
{
"mutation": "Remove",
"path": ["features", "legacy"]
}
If a mutation cannot be applied, for example because a path traverses a scalar value as if it were an object, evaluation fails and the caller reports the error according to the API using the mutation.
Evaluation Errors
The evaluator classifies each error with:
| Field | Meaning |
|---|---|
kind | Error classification. |
message | Human-readable explanation. |
path | Logical evaluation location, such as a named value, JSON path, or expression operator. |
These diagnostics are implementation details rather than public API payloads. Operation APIs retain or return concise formatted error messages at the relevant step, gate, or selector boundary.
Error kinds are:
| Kind | Meaning |
|---|---|
MissingNamedValue | A named value was not present in the evaluation context. |
MissingPath | A JSON path did not resolve. |
InvalidType | An expression received a value of the wrong JSON type. |
InvalidOperation | The expression or path is invalid. |
InvalidVersion | A value was not a valid version. |
InvalidVersionRequirement | A version requirement could not be parsed. |
Sidex Schema
The public API types are defined in the json Sidex schema:
schema json
JSON types.
JsonValue
JSON value.
JSON shape: any