Expresiones de valor (Value Expressions)

Última actualización: 20 de julio de 2026

Cada lugar de un Script donde se necesita un valor (una URL, un body de petición, un valor de campo, una condición, un valor de filtro, un id de destino, etc.) adopta una de las tres formas siguientes. Este documento describe esas tres formas, de dónde vienen los valores (las raíces de contexto) y las reglas de mapa de locales específicas de los datos de WEEGLOO. Todos los campos del Catálogo de statements siguen estas reglas.

Las tres formas

FormaReglaEjemplo
Referencia (reference)Resuelve un { /json-pointer } dentro de una cadena contra el contexto."{ /payload/fields/title }"
Literal (literal)Un valor sin { /ptr } (una cadena, número, booleano, objeto o array). Se usa tal cual."draft", 42, true, { "a": 1 }
Operaciones y condiciones (JsonLogic)Un objeto cuya única clave es un operador. Sus operandos son a su vez expresiones de valor (referencias, literales o anidamientos).{ "+": [ "{ /vars/n }", 1 ] }

Las tres formas se anidan: se coloca una referencia en un operando de JsonLogic y el resultado de esa referencia se introduce a su vez en otra operación.

Referencia: { /json-pointer }

Dentro de las llaves se coloca un JSON Pointer de RFC 6901 (que debe empezar por /). Se permiten espacios en blanco alrededor de las llaves ({ /a/b } es igual que {/a/b}).

Pointer único frente a plantilla mixta: reglas de tipo

  • Cuando toda la cadena es un único pointer, el valor conserva su tipo original (si es número, número; si es objeto, objeto; si es array, array).
  • Cuando se mezcla con texto literal, el resultado es concatenación de cadenas (concatenation).
"{ /payload/fields/count }"                 // si es un valor numérico, número tal cual (p. ej. 42)
"{ /payload/fields/tags }"                  // si es un array, array tal cual
"page-{ /payload/fields/n }-of-10"          // concatenación de cadenas → "page-42-of-10"
"Bearer { /payload/fields/token }"          // concatenación de cadenas → "Bearer abc123"

Valores ausentes y escape

  • Cuando la ruta no existe o el valor está vacío, un pointer único se convierte en null y una plantilla mixta se convierte en una cadena vacía.
  • Para usar { como literal, escápelo como \{ (esa posición no se interpreta como pointer).

Raíces de contexto: de dónde vienen los valores

El segmento de nivel superior de un { /pointer } es uno de los cinco siguientes.

RaízContenido
/payloadEl payload JSON (la entrada) que se pasa en la llamada. Ejemplo: { /payload/fields/email }
/headersLos headers HTTP de la petición que se pasan en la llamada. Las claves están en minúsculas y hay un único valor por nombre. Ejemplo: { /headers/authorization }
/<name>El resultado de un statement anterior que lleva ese name. Ejemplo: { /order/sys/id }
/vars/<name>Una variable mutable de ámbito de script declarada con SetVar. Ejemplo: { /vars/total }
/errorSe usa solo dentro del bloque catch de un Try. El error capturado, { message, statement }. Ejemplo: { /error/message }

La forma del resultado de un statement

La forma del resultado de un statement que lleva un name varía según el tipo.

StatementForma del resultadoEjemplo de referencia
Http{ status, body }{ /resp/status }, { /resp/body/choices/0/message/content }
ResourceCreate, ResourceRead (individual), ResourceFind (individual)El recurso en sí{ /post/sys/id }, { /post/fields/title/en-US }
ResourcePageRead{ items, next }{ /page/items/0/sys/id }, { /page/next }
  • ResourceFind vincula null cuando no hay coincidencia. Ramifique según la existencia con { "==": [ "{ /found }", null ] }.
  • ResourceRead (individual) es un error cuando el destino no existe (se puede gestionar con Try). Se explica en detalle en Lectura de recursos en el Catálogo de Statements.

Operaciones y condiciones: JsonLogic

Cuando necesite un cálculo o una condición, use un objeto de operador de la especificación de jsonlogic.com.

  • El acceso a los datos se unifica con referencias { /ptr }, no con el var vanilla (dot-path). El motor resuelve primero los pointers de los operandos y luego aplica el operador.
  • Cuando la clave de un objeto de clave única es un operador registrado, se trata como una operación; si no, como un objeto normal.

Tabla de operadores

CategoríaOperadorSignificado y ejemplo
Condiciónif (alias ?:){ "if": [cond, entonces, cond2, entonces2, …, predeterminado] }. El valor de la primera condición verdadera; si no hay ninguna, el último predeterminado.
Lógicaand, orEvaluación en cortocircuito. and devuelve el primer operando falsy (o el último), or el primer operando truthy (o el último), como valor.
Lógica! (not), !! (to-bool){ "!": x } niega el truthy, { "!!": x } indica si es truthy. Para comprobar la existencia se usa a menudo !!.
Igualdad==, !=Comparación laxa (compara tras la conversión numérica forzada; "1"==1 es verdadero).
Igualdad===, !==Comparación estricta (incluye el tipo).
Comparación<, <=, >, >=Encadenable: { "<": [1,2,3] } es 1<2 AND 2<3. Si un valor no se puede convertir a número (NaN), es false.
Aritmética+La suma de todos los operandos.
Aritmética-Con un operando, negación; con dos, resta.
Aritmética*, /, %Multiplicación, división, resto.
Agregaciónmin, maxEl mínimo y el máximo de los operandos.
CadenacatConcatena todos los operandos como cadenas.
Pertenenciain{ "in": [needle, haystack] }. Si haystack es una cadena, subcadena; si es una colección, pertenencia de elemento.
ArraymergeAplana varios arrays o valores en un único array (se usa para acumulación).

Los operadores de iteración de arrays (map, filter, reduce, all, some, none) no se admiten. Script recorre los arrays con Loop (Loop en el Catálogo de Statements).

Conversión numérica y ejemplos

Las reglas de conversión numérica son las siguientes. Un número se deja tal cual, true se convierte en 1, false en 0, una cadena se parsea (si no se puede parsear, el cálculo produce un valor de fallo) y null se convierte en 0.

{ "-":  [ "{ /wallet/fields/balance/en-US }", "{ /payload/fields/cost }" ] }   // saldo - coste
{ "<":  [ "{ /wallet/fields/balance/en-US }", "{ /payload/fields/cost }" ] }   // saldo < coste → boolean
{ "and": [ { "<": [ "{ /a/body/risk }", 0.5 ] }, { ">=": [ "{ /b/body/score }", 700 ] } ] }
{ "cat": [ "id-", "{ /payload/sys/id }" ] }                                    // "id-<uuid>"
{ "!!": "{ /found/sys/id }" }                                                  // true si existe
{ "merge": [ "{ /vars/ids }", [ "{ /row/sys/id }" ] ] }                        // acumula un elemento en el array
{ "if": [ "{ /page/next }", "{ /page/next }", "END" ] }                        // next si existe, si no "END"

Evaluación de verdadero y falso (Truthiness)

if, and, or, !, !!, junto con If.condition y Loop.while, determinan verdadero y falso según las reglas siguientes.

  • falsy: null, false, el número 0, la cadena vacía "", una colección vacía (un array vacío).
  • truthy: todo lo demás (números distintos de 0, cadenas y arrays no vacíos, y todos los objetos).

Las claves también pueden ser referencias

Las claves de un mapa como fields también admiten referencias { /ptr }. La clave se resuelve en tiempo de ejecución.

"fields": { "{ /payload/fields/fieldName }": { "en-US": "{ /payload/fields/fieldValue }" } }

Si dos claves se resuelven al mismo valor, colisionan y es un error del motor.

Mapa de locales (LocaleValueMap): reglas específicas de Content y Media

En WEEGLOO, cada campo de un Content o Media no es un valor sino un mapa por locale (por ejemplo, balance es { "en-US": 1, "ko-KR": 10 }). Por eso, al leer y escribir hay que gestionar el locale de forma conjunta. En Media también, title y description (escalares) y file (la instrucción de ingesta) son mapas de locales. El JSON que no es Content ni Media, como /payload o una respuesta HTTP, no se ve afectado por esta regla (mantiene la estructura que define el esquema, y un escalar sigue siendo un escalar).

Lectura

  • Para obtener un escalar, especifique hasta el locale: { /<name>/fields/<field>/<locale> } (por ejemplo, { /post/fields/title/en-US }).
  • Sin locale, { /<name>/fields/<field> } devuelve el objeto completo del mapa de locales.
  • Un campo localized:false está solo en el bucket del locale predeterminado, así que se lee con el código de ese locale predeterminado.

Escritura (los fields de ResourceCreate, ResourceUpdate, ResourcePatch)

El valor es un mapa de locales, { "<locale>": <expresión de valor escalar> }. Es simétrico con la lectura.

"fields": {
  "title":  { "en-US": "Hello", "ko-KR": "안녕" },   // enumera buckets para varios locales
  "status": { "en-US": "paid" }
}
  • ResourceCreate debe incluir el bucket del locale predeterminado del Space en cada campo que rellena (la regla default-locale).
  • ResourceUpdate es un reemplazo completo. Los campos y locales que no estén en fields se eliminan (incluido el archivo).
  • ResourcePatch actualiza solo los campos y buckets especificados (los demás campos y locales se mantienen).
  • Eliminación con un null literal: cuando el valor es un null literal, se elimina ese bucket (field, locale) (la forma estándar de vaciar un locale concreto en un Patch). "" (una cadena vacía) no es una eliminación, sino que establece un valor vacío. Cuando una expresión de valor ({ /ptr }) se evalúa como null en tiempo de ejecución, no es una eliminación sino un error (un payload ausente no se traga en silencio). Solo un null literal elimina.
  • Media file: el valor no es un escalar sino una instrucción de ingesta, { "source": …, "encoding": "url"|"base64" }. Una escritura que incluye un archivo es exclusiva de Async (ResourceCreate en el Catálogo de Statements).
  • Un campo localized:false se coloca solo en el bucket del locale predeterminado.
  • El código de locale (la clave del mapa) también puede ser una referencia { /ptr } (véase arriba Las claves también pueden ser referencias). Se usa para crear locales dinámicos.

Campo de conveniencia locale

Si se da locale a ResourceCreate, ResourceUpdate o ResourcePatch, el motor envuelve automáticamente cada valor de fields en un bucket { <locale>: valor }. Es decir, basta con dar escalares.

// los dos siguientes son equivalentes
{ "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" } } }

Si se da locale y el valor ya anida un mapa de locales ({ "en-US": … }), se produce un anidamiento doble como { <locale>: { "en-US": … } } (error del autor). Unifique en un solo estilo: con locale, solo escalares; sin él, solo mapas de locales explícitos.

El locale en where y order

  • En where y order, para fields.X el motor aplica automáticamente el locale predeterminado del Space (igual que una consulta de CMA).
  • Para apuntar a un locale específico, especifíquelo como fields.X.<locale>.
"where": { "fields.slug": { "eq": "{ /payload/fields/slug }" } }   // slug del locale predeterminado
"where": { "fields.title.ko-KR": { "prefix": "안" } }              // locale específico