# Entendendo os operadores JOLT (wildcards)

Os operadores do JOLT, também conhecidos como **wildcards**, são um dos recursos mais poderosos do framework. Eles permitem manipular valores, capturar nomes de campos, lidar com entradas opcionais e criar estruturas flexíveis mesmo quando o formato de entrada varia.

Neste guia, você verá como cada operador funciona, que tipo de problema ele resolve e como usá-lo para simplificar cenários de transformação básicos e avançados.

{% hint style="success" %}
**Dica:** Teste os exemplos deste documento no [JOLT playground](https://jolt-demo.appspot.com/#inception).
{% endhint %}

## **Conceitos importantes**

Até agora, cobrimos os conceitos essenciais do JOLT. Antes de avançar para as operações avançadas, precisamos apresentar dois elementos fundamentais usados em todas as especificações JOLT: **LHS** e **RHS**.

### **LHS e RHS**

Toda operação JOLT é construída em torno de dois lados:

* **LHS (Left Hand Side):** A parte antes dos dois-pontos (`:`), onde **selecionamos** ou **casamos** campos da entrada.
* **RHS (Right Hand Side):** A parte depois dos dois-pontos (`:`), onde **atribuímos** ou **mapeamos** valores para a saída.

Os operadores se comportam de maneiras diferentes no **LHS** e no **RHS**, e entender essa distinção é essencial para criar regras de transformação poderosas e flexíveis.

Exemplo:

```json
[
 {
   "operation": "shift",
   "spec": {
LHS -> "customer": {
 LHS ->  "name": "client.fullName",  <- RHS
 LHS ->  "birhtDate": "client.dateOfBirth",  <- RHS
 LHS ->  "address": "client.address.street",  <- RHS
 LHS ->  "country": "client.address.country"  <- RHS
     }
   }
 }
}
```

## **Análise detalhada dos operadores**

Vamos analisar cada operador e observar como ele se comporta em transformações reais. Nas próximas seções, você encontrará explicações e exemplos que mostram exatamente como cada operador funciona e qual tipo de saída produz.

### **& (“e” comercial)**

Usa o **nome do campo encontrado no LHS** para construir a estrutura no JSON de saída, sem exigir que você defina o nome manualmente no RHS.

* **Uso:** RHS
* **Operação:** `shift`

#### **Exemplo prático**

* **Caso de uso:** Agrupar campos relacionados de um cliente em um único objeto.
* **Objetivo:** Mover os campos existentes para um novo objeto `client` sem renomeá-los.

**JSON de entrada**

```json
{
 "name": "Client Example",
 "email": "client-example@email.com"
}
```

**JSON de saída desejado**

```json
{
 "client": {
   "name": "Client Example",
   "email": "client-example@email.com"
 }
}
```

**Spec de transformação**

```json
[
 {
   "operation": "shift",
   "spec": {
     "name": "client.&",
     "email": "client.&"
   }
 }
]
```

**Explicação**

Essa transformação move os campos originais `name` e `email` para dentro de um novo objeto `client`.

O wildcard `&` mantém **o mesmo nome de campo** do input ao criar a estrutura de saída.

* `"name": "client.&"` pega o valor de `name` e o coloca em `client.name`.
* `"email": "client.&"` faz o mesmo para `email`, gerando `client.email`.

Ao usar `&`, você não precisa repetir manualmente cada nome de campo no RHS. O JOLT preserva automaticamente o nome original enquanto organiza os campos dentro de `client`.

### **\* (asterisco)**

Refere-se a **todos os campos ou objetos**, sem precisar listar cada um explicitamente.

* **Uso:** LHS
* **Operações:** `shift`, `remove`, `cardinality`, `modify-default-beta`, `modify-overwrite-beta`

#### **Exemplo prático**

* **Caso de uso:** Organizar os dados de um cliente agrupando todos os campos sob um único objeto pai.
* **Objetivo:** Aninhar todos os campos dentro de um objeto `customer` e renomear `document` para `ssn`.

**JSON de entrada**

```json
{
 "name": "Customer Example",
 "email": "cliente-exemplo@email.com",
 "document": "1234567890",
 "birthDate": "10/31/1990",
 "address": "Customer Example Street"
}
```

**JSON de saída desejado**

```json
{
 "customer": {
   "name": "Customer Example",
   "email": "client-example@email.com",
   "document": "1234567890",
   "birthDate": "10/31/1990",
   "address": "Customer Example Street"
 }
}
```

**Spec de transformação**

```json
[
 {
   "operation": "shift",
   "spec": {
     "*": "customer.&",
     "document": "customer.ssn"
   }
 }
]
```

**Explicação**

Na linha `"*": "customer.&"`, pegamos **qualquer campo encontrado no JSON de entrada** e o colocamos dentro de um novo objeto **customer**, preservando tanto o nome do campo quanto toda a sua estrutura.

Para o campo `document`, pegamos seu valor e o mapeamos para um novo campo chamado `ssn`, também dentro do objeto `customer`.

**Como funciona:**

* `*` corresponde a **qualquer campo**.
* `&` mantém o **nome e o valor originais** do campo.
* Quando usados juntos (`*` + `&`), o JOLT copia automaticamente todos os campos correspondentes **sem que você precise especificá-los um por um**.

Essa combinação é útil quando você precisa **manipular ou reorganizar um JSON** sem conhecer toda a sua estrutura com antecedência.

### **@ (arroba)**

Faz referência ao **valor** de um campo.

Seu comportamento muda dependendo da operação e de estar no LHS ou RHS.

* **Uso:** LHS e RHS
* **Operações:** `shift`, `modify-default-beta`, `modify-overwrite-beta`

#### **Exemplo com `shift`**

* **Caso de uso:** Criar nomes de campos dinamicamente com base nos valores de entrada.
* **Objetivo:** Usar o valor de `key` para definir o nome do campo dentro de `product`, atribuindo a ele o valor de `value`.

**JSON de entrada**

```json
{  
   "key": "code",  
   "value": "123-ABC"
}
```

**JSON de saída desejado**

```json
{  
   "product": {    
       "code": "123-ABC"  
   }
}
```

**Spec de transformação**

```json
[
 {
   "operation": "shift",
   "spec": {
     "value": "product.@(1,key)"
   }
 }
]
```

**Explicação**

Em `product.@(1,key)`, a expressão `@(1,key)` diz ao JOLT para:

* Subir **um nível** (por causa do `1`),
* Encontrar o campo chamado **`key`**,
* Usar seu **valor (`"code"`) como nome do novo campo** dentro de `product`.

Isso significa que o valor de `"value"` (`"123-ABC"`) é atribuído a um campo com nome dinâmico (`"code"`).

**Como o @ funciona:**

* `@` faz referência a dados de outra parte do JSON.
* O primeiro argumento (`1`) indica **quantos níveis acima** procurar.
* O segundo argumento (`key`) indica **qual valor de campo recuperar**.
* A mesma lógica se aplica quando `@` é usado no LHS ou RHS do spec.

Esse mecanismo permite **criar nomes de campo dinamicamente** com base em valores do JSON de entrada, proporcionando transformações mais flexíveis.

#### **Exemplos de `modify-default-beta` e `modify-overwrite-beta`**

* **Caso de uso:** Enriquecer um objeto aninhado com informações armazenadas em outra parte do JSON.
* **Objetivo:** Adicionar um campo `company` dentro de `product`, usando o valor do campo de nível superior `manufacturer`.

**JSON de entrada**

```json
{
 "product": {
   "name": "Produto A",
   "price": 10
 },
 "manufacturer": "Company A"
}
```

**JSON de saída desejado**

```json
{
 "product": {
   "name": "Product A",
   "price": 10,
   "company": "Company A"
 },
 "manufacturer": "Company A"
}
```

**Spec de transformação**

```json
[
 {
   "operation": "modify-default-beta",  //para modify-overwrite-beta 
   "spec": {                            //nós teríamos a mesma transformação
     "produto": {                       <- nível 2   
       "company": "@(2,manufacturer)"   <- nível 1 
     }
   }
 }
]
```

**Explicação**

Criamos um novo campo chamado **`company`** dentro do objeto `product` e atribuímos a ele o valor do campo **`manufacturer`**.

Para isso, usamos `@(2,manufacturer)`, que instrui o JOLT a:

* Subir **dois níveis** (a partir de dentro de `product`),
* Encontrar o campo chamado **`manufacturer`**,\
  Recuperar **seu valor e atribuí-lo a `product.company`**.

**`modify-default-beta` vs. `modify-overwrite-beta`**

* **`modify-default-beta`:** Adiciona o campo `company` **somente se ele ainda não existir** dentro de `product`. Ele preserva valores existentes.
* **`modify-overwrite-beta`:** Adiciona o campo `company` **mesmo que ele já exista**, sempre substituindo o valor existente. Como o nome sugere, ele **sobrescreve** qualquer conteúdo anterior.

Ambas as operações usam o mesmo spec de transformação. A única diferença é o comportamento em relação à sobrescrita.

### **$ (cifrão)**

Faz referência **ao nome de um campo**, em vez de seu valor.

* **Uso:** LHS
* **Operação:** `shift`

#### **Exemplo prático**

* **Caso de uso:** Identificar quais campos existem dentro de um objeto `product`.
* **Objetivo:** Gerar uma lista com os nomes de todos os campos dentro de `product`.

**JSON de entrada**

```json
{
 "product": {
   "name": "Product Example",
   "value": 10,
   "category": "CATEG-1",
   "weight": 25
 }
}
```

**JSON de saída desejado**

```json
{
 "product": [
   "name",
   "value",
   "category",
   "weight"
 ]
}
```

**Spec de transformação**

```json
[
 {
   "operation": "shift",
   "spec": {
     "product": {
       "*": {
         "$": "product[]"
       }
     }
   }
 }
]
```

**Explicação**

Selecionamos todos os campos (`*`) dentro do objeto `product` e usamos `$` para recuperar **o nome de cada campo**, não o seu valor. Em seguida, colocamos cada nome recuperado dentro da lista `product[]`.

Isso permite gerar uma estrutura que captura **apenas os nomes dos campos** do JSON de entrada.

### **# (cerquilha)**

O operador `#` possui funções diferentes dependendo de onde é usado:

* **Uso:**
  * **LHS:** Permite inserir **valores manuais (constantes)** no JSON de saída.
  * **RHS:** Usado **exclusivamente para criar listas**, agrupando conteúdo de níveis superiores em uma nova estrutura de lista.
* **Operação:** `shift`

#### **Exemplo no LHS**

* **Caso de uso:** Adicionar um campo ausente que não é fornecido no JSON de entrada.
* **Objetivo:** Inserir um campo padrão `category` dentro de `product`, preservando todos os campos existentes.

**JSON de entrada**

```json
{ 
 "product": { 
   "name": "Product Example", 
   "value": 10, 
   "weight": 25 
 } 
}
```

**JSON de saída desejado**

```json
{
  "product" : {
    "category" : "DEFAULT-CATEGORY",
    "name" : "Product Example",
    "value" : 10,
    "weight" : 25
  }
}
```

**Spec de transformação**

```json
[
 {
   "operation": "shift",
   "spec": {
     "product": {
       "*": "product.&",
       "#DEFAULT-CATEGORY": "product.category"
     }
   }
 }
]
```

**Explicação**

O valor após o curinga `#` (**`DEFAULT-CATEGORY`**) é **inserido manualmente** no campo especificado no RHS (`product.category`).

Isso garante que o campo seja sempre incluído, independentemente da entrada.

#### **Exemplo no RHS**

* **Caso de uso:** Padronizar nomes de campos dentro de uma lista de objetos `products`.
* **Objetivo:** Renomear o campo `value` para `price` em cada item do array `products`.

**JSON de entrada**

```json
{
 "products": [
   {
     "code": "PROD-A",
     "value": 10
   },
   {
     "code": "PROD-B",
     "value": 20
   }
 ]
}
```

**JSON de saída desejado**

```json
{  
 "products": [
   {
     "code": "PROD-A",
     "price": 10
   },
   {
     "code": "PROD-B",
     "price": 20
   }
 ]
}
```

**Spec de transformação**

```json
[
  {
    "operation": "shift",
    "spec": {
      "products": {                      // level 2
        "*": {                           // level 1
          "code": "products[#2].&",      // level 0
          "value": "products[#2].price"  // level 0
        }
      }
    }
  }
]
```

**Explicação**

Usar `#` no RHS significa:

* Estamos **criando uma lista** (`[...]`).
* `#2` indica ao JOLT que deve agrupar os elementos com base na estrutura encontrada **dois níveis acima**.
* Isso garante que cada `code` e seu respectivo `price` permaneçam juntos dentro do mesmo objeto `product`.

Portanto:

* `"code": "products[#2].&"`: Pega o valor de `code` e o coloca no campo `code` dentro da nova lista `products`.
* `"value": "products[#2].price"`: Pega o campo `value` e o grava como `price` dentro do mesmo item da lista.

Ao olhar **2 níveis acima**, o JOLT preserva o agrupamento original de cada produto ao formar a nova lista.

### **| (pipe)**

O operador `|` permite fazer referência a **múltiplos nomes de campo possíveis** no JSON de entrada e mapear todos eles para o **mesmo destino** no JSON de saída.

Isso é útil quando a estrutura de entrada pode variar, mas a saída precisa permanecer consistente.

* **Uso:** LHS
* **Operação:** `shift`

#### **Exemplo prático**

* **Caso de uso:** Tratar diferentes convenções de nomenclatura para o mesmo campo de cliente.
* **Objetivo:** Mapear `fullName` ou `customerName` para um campo unificado `name`.

**JSON de entrada**

```json
{
 "customer": {
   "fullName": "Customer Example",
   "email": "customer-example@email.com"
 }
}
```

**JSON de saída desejado**

```json
{
 "customer": {
   "name": "Customer Example",
   "email": "customer-example@email.com"
 }
}
```

**Spec de transformação**

```json
[
 {
   "operation": "shift",
   "spec": {
     "customer": {
       "fullName|customerName": "customer.nome",
       "email": "customer.&"
     }
   }
 }
]
```

**Explicação**

* `"fullName|customerName"` significa: se `fullName` **ou** `customerName` estiver presente, seu valor será atribuído a `customer.name`.
* `"email": "customer.&"` preserva o nome do campo e mapeia o valor de `email` como está.

Isso garante que a saída permaneça consistente mesmo quando a entrada usa diferentes convenções de nomenclatura.

## **Continue aprendendo**

Agora que você entende como esse operador funciona, aqui estão alguns próximos passos que você pode explorar:

* [**Operações avançadas**](/documentation/resources/pt-br/use-cases/how-to-jolt/advanced-operations.md), onde você aprofunda recursos de transformação mais poderosos.
* [**Exemplos de uso**](/documentation/resources/pt-br/use-cases/how-to-jolt/use-cases.md), mostrando como o JOLT é aplicado em cenários reais de integração.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.digibee.com/documentation/resources/pt-br/use-cases/how-to-jolt/operators.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
