Expressões de valor (Value Expressions)

Última atualização: 20 de julho de 2026

Todo lugar em um Script onde é necessário um valor (uma URL, um corpo de requisição, um valor de campo, uma condição, um valor de filtro, um id de destino, etc.) assume uma das três formas abaixo. Este documento descreve essas três formas, de onde vêm os valores (as raízes de contexto) e as regras de mapa de locales específicas dos dados do WEEGLOO. Todos os campos do Catálogo de statements seguem essas regras.

As três formas

FormaRegraExemplo
Referência (reference)Resolve um { /json-pointer } dentro de uma string contra o contexto."{ /payload/fields/title }"
Literal (literal)Um valor sem { /ptr } (uma string, número, booleano, objeto ou array). Usado tal como está."draft", 42, true, { "a": 1 }
Operações e condições (JsonLogic)Um objeto que tem um único operador como chave. Os operandos são, por sua vez, expressões de valor (referências, literais ou aninhamentos).{ "+": [ "{ /vars/n }", 1 ] }

As três formas se aninham: você coloca uma referência em um operando de JsonLogic e reintroduz o resultado dessa referência em outra operação.

Referência: { /json-pointer }

Coloque um JSON Pointer conforme a RFC 6901 (que deve começar com /) dentro das chaves. Espaços em branco ao redor das chaves são permitidos ({ /a/b } é igual a {/a/b}).

Pointer único vs. template misto: regras de tipo

  • Quando toda a string é um único pointer, o valor mantém seu tipo original (se for número, número; se for objeto, objeto; se for array, array).
  • Quando é misturado com texto literal, o resultado é concatenação de strings (concatenation).
"{ /payload/fields/count }"                 // se for um valor numérico, número tal como está (ex.: 42)
"{ /payload/fields/tags }"                  // se for um array, array tal como está
"page-{ /payload/fields/n }-of-10"          // concatenação de strings → "page-42-of-10"
"Bearer { /payload/fields/token }"          // concatenação de strings → "Bearer abc123"

Valores ausentes e escape

  • Quando o caminho não existe ou o valor está vazio, um único pointer se torna null e um template misto se torna uma string vazia.
  • Para usar { como literal, escape-o como \{ (essa posição não é interpretada como pointer).

Raízes de contexto: de onde vêm os valores

O segmento de nível superior de um { /pointer } é um dos cinco a seguir.

RaizConteúdo
/payloadO payload JSON (a entrada) passado na chamada. Exemplo: { /payload/fields/email }
/headersOs cabeçalhos HTTP da requisição passados na chamada. As chaves são minúsculas, com um único valor por nome. Exemplo: { /headers/authorization }
/<name>O resultado de um statement anterior que carrega esse name. Exemplo: { /order/sys/id }
/vars/<name>Uma variável mutável com escopo de script declarada com SetVar. Exemplo: { /vars/total }
/errorUsado somente dentro do bloco catch de um Try. O erro capturado, { message, statement }. Exemplo: { /error/message }

A forma do resultado de um statement

A forma do resultado de um statement que carrega um name varia conforme o tipo.

StatementForma do resultadoExemplo de referência
Http{ status, body }{ /resp/status }, { /resp/body/choices/0/message/content }
ResourceCreate, ResourceRead (individual), ResourceFind (individual)O próprio recurso{ /post/sys/id }, { /post/fields/title/en-US }
ResourcePageRead{ items, next }{ /page/items/0/sys/id }, { /page/next }
  • ResourceFind vincula null quando não há correspondência. Faça a ramificação por existência com { "==": [ "{ /found }", null ] }.
  • ResourceRead (individual) é um erro quando o alvo não existe (é possível tratá-lo com Try). Os detalhes são abordados em Leitura de recursos no Catálogo de statements.

Operações e condições: JsonLogic

Quando precisar de um cálculo ou uma condição, use um objeto operador da especificação de jsonlogic.com.

  • O acesso aos dados é unificado em referências { /ptr }, não no var vanilla (dot-path). O motor resolve primeiro os pointers dos operandos e depois aplica o operador.
  • Quando a chave de um objeto de chave única é um operador registrado, ela é tratada como uma operação; caso contrário, como um objeto comum.

Tabela de operadores

CategoriaOperadorSignificado e exemplo
Condiçãoif (alias ?:){ "if": [cond, então, cond2, então2, …, padrão] }. O valor da primeira condição verdadeira; se não houver nenhuma, o último padrão.
Lógicaand, orAvaliação em curto-circuito. and retorna o primeiro operando falsy (ou o último); or, o primeiro truthy (ou o último), como valor.
Lógica! (not), !! (to-bool){ "!": x } nega o truthy; { "!!": x } indica se é truthy. Para verificar a existência, usa-se !! com frequência.
Igualdade==, !=Comparação frouxa (compara após conversão numérica forçada; "1"==1 é verdadeiro).
Igualdade===, !==Comparação estrita (incluindo o tipo).
Comparação<, <=, >, >=Encadeável: { "<": [1,2,3] } significa 1<2 AND 2<3. Se um valor não puder ser convertido em número (NaN), é false.
Aritmética+A soma de todos os operandos.
Aritmética-Com um operando, negação; com dois, subtração.
Aritmética*, /, %Multiplicação, divisão, resto.
Agregaçãomin, maxO mínimo e o máximo dos operandos.
StringcatConcatena todos os operandos como strings.
Pertencimentoin{ "in": [needle, haystack] }. Se o haystack for uma string, é substring; se for uma coleção, é pertencimento de elemento.
ArraymergeAchata vários arrays ou valores em um único array (usado para acumulação).

Os operadores de iteração de arrays (map, filter, reduce, all, some, none) não são suportados. O Script percorre um array com Loop (Loop no Catálogo de statements).

Conversão numérica e exemplos

As regras de conversão numérica são as seguintes. Um número é mantido como está, true vira 1, false vira 0, uma string é parseada (se não puder ser parseada, o cálculo produz um valor de falha) e null vira 0.

{ "-":  [ "{ /wallet/fields/balance/en-US }", "{ /payload/fields/cost }" ] }   // saldo - custo
{ "<":  [ "{ /wallet/fields/balance/en-US }", "{ /payload/fields/cost }" ] }   // saldo < custo → boolean
{ "and": [ { "<": [ "{ /a/body/risk }", 0.5 ] }, { ">=": [ "{ /b/body/score }", 700 ] } ] }
{ "cat": [ "id-", "{ /payload/sys/id }" ] }                                    // "id-<uuid>"
{ "!!": "{ /found/sys/id }" }                                                  // true se existir
{ "merge": [ "{ /vars/ids }", [ "{ /row/sys/id }" ] ] }                        // acumula um elemento no array
{ "if": [ "{ /page/next }", "{ /page/next }", "END" ] }                        // next se existir, caso contrário "END"

Avaliação de verdadeiro e falso (Truthiness)

if, and, or, !, !!, junto com If.condition e Loop.while, determinam verdadeiro e falso pelas regras a seguir.

  • falsy: null, false, o número 0, a string vazia "" e uma coleção vazia (um array vazio).
  • truthy: todo o resto (números diferentes de 0, strings e arrays não vazios, e todos os objetos).

As chaves também podem ser referências

As chaves de um mapa como fields também suportam referências { /ptr }. A chave é resolvida em tempo de execução.

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

Se duas chaves forem resolvidas para o mesmo valor, elas colidem e é um erro do motor.

Mapa de locales (LocaleValueMap): regras específicas de Content e Media

No WEEGLOO, cada campo de um Content ou Media não é um valor, mas um mapa por locale (por exemplo, balance é { "en-US": 1, "ko-KR": 10 }). Por isso, ao ler e escrever, é preciso tratar o locale em conjunto. No Media também, title e description (escalares) e file (a instrução de ingestão) são mapas por locale. O JSON que não é Content nem Media, como /payload ou uma resposta HTTP, não é afetado por essa regra (mantém a estrutura definida pelo esquema, e um escalar continua sendo um escalar).

Leitura

  • Para obter um escalar, especifique até o locale: { /<name>/fields/<field>/<locale> } (por exemplo, { /post/fields/title/en-US }).
  • Sem locale, { /<name>/fields/<field> } retorna o objeto completo do mapa por locale.
  • Um campo localized:false fica somente no bucket do locale padrão, portanto leia-o com o código desse locale padrão.

Escrita (os fields de ResourceCreate, ResourceUpdate e ResourcePatch)

O valor é um mapa por locale, { "<locale>": <expressão de valor escalar> }. É simétrico com a leitura.

"fields": {
  "title":  { "en-US": "Hello", "ko-KR": "안녕" },   // enumera os buckets para vários locales
  "status": { "en-US": "paid" }
}
  • ResourceCreate deve incluir o bucket do locale padrão do Space em todos os campos que preenche (a regra default-locale).
  • ResourceUpdate é uma substituição completa. Os campos e locales ausentes de fields são removidos (incluindo o arquivo).
  • ResourcePatch atualiza somente os campos e buckets especificados (os demais campos e locales são mantidos).
  • Exclusão com um null literal: quando o valor é um null literal, esse bucket (field, locale) é excluído (a forma padrão de esvaziar um locale específico em um Patch). "" (uma string vazia) não é uma exclusão, mas define um valor vazio. Quando uma expressão de valor ({ /ptr }) é avaliada como null em tempo de execução, não é uma exclusão, mas um erro (um payload ausente não é ignorado silenciosamente). Somente um null literal exclui.
  • Media file: o valor não é um escalar, mas uma instrução de ingestão, { "source": …, "encoding": "url"|"base64" }. A escrita que inclui um arquivo é exclusiva do modo Async (ResourceCreate no Catálogo de statements).
  • Coloque um campo localized:false somente no bucket do locale padrão.
  • O código de locale (a chave do mapa) também pode ser uma referência { /ptr } (veja acima As chaves também podem ser referências). Use isso para criar um locale dinâmico.

Campo de conveniência locale

Ao passar locale para ResourceCreate, ResourceUpdate ou ResourcePatch, o motor envolve automaticamente cada valor de fields em um bucket { <locale>: valor }. Ou seja, basta passar escalares.

// os dois abaixo são 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" } } }

Se você passar locale enquanto o valor já aninha um mapa por locale ({ "en-US": … }), ocorre um aninhamento duplo como { <locale>: { "en-US": … } } (erro do autor). Padronize um único estilo: com locale, use somente escalares; sem ele, use somente mapas de locale explícitos.

O locale em where e order

  • Em where e order, para fields.X o motor aplica automaticamente o locale padrão do Space (igual a uma consulta na CMA).
  • Para direcionar a um locale específico, indique-o explicitamente como fields.X.<locale>.
"where": { "fields.slug": { "eq": "{ /payload/fields/slug }" } }   // slug do locale padrão
"where": { "fields.title.ko-KR": { "prefix": "안" } }              // locale específico