Value expressions
Last updated: July 20, 2026
Everywhere a value is needed in a Script (a URL, a request body, a field value, a condition, a filter value, a target id, and so on) takes one of the three forms below. This document explains those three forms, where values come from (the context roots), and the locale-map rules specific to WEEGLOO data. Every field in the Statement catalog follows these rules.
The three forms
| Form | Rule | Example |
|---|---|---|
| Reference | Resolves a { /json-pointer } inside a string against the context. | "{ /payload/fields/title }" |
| Literal | A value with no { /ptr } (a string, number, boolean, object, or array). Used as-is. | "draft", 42, true, { "a": 1 } |
| Operations and conditions (JsonLogic) | An object whose single key is an operator. Its operands are themselves value expressions (references, literals, or nested operations). | { "+": [ "{ /vars/n }", 1 ] } |
The three forms nest: you put a reference in a JsonLogic operand, then feed that reference's result back into another operation.
Reference: { /json-pointer }
Put an RFC 6901 JSON Pointer (which must start with /) inside the braces. Whitespace around the braces is allowed ({ /a/b } is the same as {/a/b}).
Single pointer vs. mixed template: type rules
- When the entire string is a single pointer, the value keeps its original type (a number stays a number, an object stays an object, an array stays an array).
- When it is mixed with literal text, the result is string concatenation.
"{ /payload/fields/count }" // a number value stays a number (e.g. 42)
"{ /payload/fields/tags }" // an array stays an array
"page-{ /payload/fields/n }-of-10" // string concatenation → "page-42-of-10"
"Bearer { /payload/fields/token }" // string concatenation → "Bearer abc123"Missing values and escaping
- When the path is absent or the value is empty, a single pointer becomes
nulland a mixed template becomes an empty string. - To use
{as a literal, escape it as\{(that position is not interpreted as a pointer).
Context roots: where values come from
The top-level segment of a { /pointer } is one of the five below.
| Root | Contents |
|---|---|
/payload | The JSON payload (the input) passed on the call. Example: { /payload/fields/email } |
/headers | The request HTTP headers passed on the call. Keys are lowercase, with a single value per name. Example: { /headers/authorization } |
/<name> | The result of an earlier statement that carries that name. Example: { /order/sys/id } |
/vars/<name> | A script-scoped mutable variable declared with SetVar. Example: { /vars/total } |
/error | Used only inside a Try block's catch. The caught error, { message, statement }. Example: { /error/message } |
The shape of a statement's result
The result shape of a statement that carries a name differs by type.
| Statement | Result shape | Reference example |
|---|---|---|
Http | { status, body } | { /resp/status }, { /resp/body/choices/0/message/content } |
ResourceCreate, ResourceRead (single), ResourceFind (single) | The resource itself | { /post/sys/id }, { /post/fields/title/en-US } |
ResourcePageRead | { items, next } | { /page/items/0/sys/id }, { /page/next } |
ResourceFindbindsnullwhen there is no match. Branch on existence with{ "==": [ "{ /found }", null ] }.ResourceRead(single) is an error when the target does not exist (you can handle it withTry). See Reading resources in the Statement catalog for details.
Operations and conditions: JsonLogic
When you need a calculation or a condition, use an operator object from the jsonlogic.com specification.
- Data access is standardized on
{ /ptr }references, not the vanillavar(dot-path). The engine resolves the operands' pointers first, then applies the operator. - When a single-key object's key is a registered operator, it is treated as an operation; otherwise it is treated as a plain object.
Operator table
| Category | Operator | Meaning and example |
|---|---|---|
| Condition | if (alias ?:) | { "if": [cond, then, cond2, then2, …, default] }. The value of the first true condition, or the last default if none. |
| Logic | and, or | Short-circuit evaluation. and returns the first falsy operand (or the last), or the first truthy operand (or the last), as a value. |
| Logic | ! (not), !! (to-bool) | { "!": x } negates truthiness; { "!!": x } gives the truthiness. !! is often used for existence checks. |
| Equality | ==, != | Loose comparison (compares after numeric coercion; "1"==1 is true). |
| Equality | ===, !== | Strict comparison (type included). |
| Comparison | <, <=, >, >= | Chainable: { "<": [1,2,3] } means 1<2 AND 2<3. If a value cannot be made numeric (NaN), it is false. |
| Arithmetic | + | The sum of all operands. |
| Arithmetic | - | With one operand, negation; with two, subtraction. |
| Arithmetic | *, /, % | Multiplication, division, remainder. |
| Aggregation | min, max | The minimum and maximum of the operands. |
| String | cat | Concatenates all operands as strings. |
| Membership | in | { "in": [needle, haystack] }. If the haystack is a string, substring; if a collection, element membership. |
| Array | merge | Flattens multiple arrays or values into a single array (used for accumulation). |
The array iteration operators (map, filter, reduce, all, some, none) are not supported. Script iterates over an array with Loop (see Loop in the Statement catalog).
Numeric coercion and examples
The numeric coercion rules are as follows. A number is left as-is, true becomes 1, false becomes 0, a string is parsed (if it cannot be parsed, the calculation produces a failure value), and null becomes 0.
{ "-": [ "{ /wallet/fields/balance/en-US }", "{ /payload/fields/cost }" ] } // balance - cost
{ "<": [ "{ /wallet/fields/balance/en-US }", "{ /payload/fields/cost }" ] } // balance < cost → boolean
{ "and": [ { "<": [ "{ /a/body/risk }", 0.5 ] }, { ">=": [ "{ /b/body/score }", 700 ] } ] }
{ "cat": [ "id-", "{ /payload/sys/id }" ] } // "id-<uuid>"
{ "!!": "{ /found/sys/id }" } // true if it exists
{ "merge": [ "{ /vars/ids }", [ "{ /row/sys/id }" ] ] } // accumulate one element into the array
{ "if": [ "{ /page/next }", "{ /page/next }", "END" ] } // next if present, otherwise "END"Truthiness
if, and, or, !, !!, along with If.condition and Loop.while, decide true and false by the following rules.
- falsy:
null,false, the number0, the empty string"", and an empty collection (an empty array). - truthy: everything else (nonzero numbers, non-empty strings and arrays, and every object).
Keys can be references too
The keys of a map such as fields also support { /ptr } references. The key is resolved at runtime.
"fields": { "{ /payload/fields/fieldName }": { "en-US": "{ /payload/fields/fieldValue }" } }If two keys resolve to the same value, they collide and it is an engine error.
Locale map (LocaleValueMap): rules specific to Content and Media
In WEEGLOO, each field of a Content or Media is not a value but a per-locale map (for example, balance is { "en-US": 1, "ko-KR": 10 }). So you must handle the locale together when you read and write. For Media as well, title and description (scalars) and file (the ingest directive) are locale maps. JSON that is not a Content or Media, such as /payload or an HTTP response, is unaffected by this rule (it keeps the structure the schema defines, and a scalar stays a scalar).
Reading
- To get a scalar, specify down to the locale:
{ /<name>/fields/<field>/<locale> }(for example,{ /post/fields/title/en-US }). - Without a locale,
{ /<name>/fields/<field> }returns the whole locale-map object. - A
localized:falsefield lives only in the default-locale bucket, so read it with that default-locale code.
Writing (the fields of ResourceCreate, ResourceUpdate, and ResourcePatch)
The value is a locale map, { "<locale>": <scalar value expression> }. It is symmetric with reading.
"fields": {
"title": { "en-US": "Hello", "ko-KR": "안녕" }, // list buckets for multiple locales
"status": { "en-US": "paid" }
}ResourceCreatemust include the space default-locale bucket in every field it populates (the default-locale rule).ResourceUpdateis a full replacement. Fields and locales absent fromfieldsare removed (including the file).ResourcePatchupdates only the specified fields and buckets (other fields and locales are kept).- Delete with a literal
null: when the value is a literalnull, that (field, locale) bucket is deleted (the standard way to clear a specific locale in a Patch).""(an empty string) is not a deletion but sets an empty value. When a value expression ({ /ptr }) evaluates to null at runtime, it is not a deletion but an error (a missing payload is not silently swallowed). Only a literalnulldeletes. Mediafile: the value is not a scalar but an ingest directive,{ "source": …, "encoding": "url"|"base64" }. A write that includes a file is Async-only (see ResourceCreate in the Statement catalog).- Put a
localized:falsefield only in the default-locale bucket. - A locale code (a map key) can also be a
{ /ptr }reference (see Keys can be references too above). Use this to build a dynamic locale.
The locale convenience field
When you give locale to ResourceCreate, ResourceUpdate, or ResourcePatch, the engine automatically wraps each value in fields in a { <locale>: value } bucket. In other words, you only need to give scalars.
// the two below are equivalent
{ "type": "ResourceCreate", "resource": "Content", "contentType": { "sys": { "id": "ct_post" } },
"locale": "en-US", "fields": { "title": "Hello" } }
{ "type": "ResourceCreate", "resource": "Content", "contentType": { "sys": { "id": "ct_post" } },
"fields": { "title": { "en-US": "Hello" } } }If you give locale while the value already nests a locale map ({ "en-US": … }), it becomes doubly nested as { <locale>: { "en-US": … } } (an authoring mistake). Standardize on one style: with locale, use scalars only; without it, use explicit locale maps only.
Locales in where and order
- In
whereandorder, forfields.Xthe engine automatically applies the space default locale (the same as a CMA query). - To target a specific locale, state it explicitly as
fields.X.<locale>.
"where": { "fields.slug": { "eq": "{ /payload/fields/slug }" } } // default-locale slug
"where": { "fields.title.ko-KR": { "prefix": "안" } } // specific localeRelated documents
- Statement catalog: The fields and results of the 17 statement types that use value expressions.
- Execution semantics, constraints, and security: Execution order, errors, optimistic locking, and static constraints.
- Cookbook: Complete examples that combine value expressions.
- Script overview: The top-level structure and execution modes.
