0Pricing
DevOps Bootcamp · Aula

Transformação e criação de objetos JSON com jq

Remodele dados com map, to_entries e construção de objetos para produzir novos conteúdos JSON.

Transformação e criação de objetos JSON com jq é uma aula grátis de DevOps Bootcamp no CoddyKit. Esta é a aula 2 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de DevOps Bootcamp, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de DevOps Bootcamp inclui 4 aulas no total.

Por que transformar JSON?

O JSON bruto de APIs ou arquivos de registro raramente tem exatamente o formato de que você precisa. Você pode receber um objeto grande, mas querer apenas campos específicos; também pode precisar renomear chaves, achatar estruturas aninhadas ou criar uma carga completamente nova para enviar a outro serviço.

jq é um processador de JSON leve e poderoso para a linha de comando que possibilita essas transformações em um único fluxo. Nesta lição, você aprenderá as três técnicas essenciais para reorganizar dados:

  • Construção de objetos — criar um novo objeto JSON do zero
  • map — aplicar uma transformação a cada elemento de uma matriz
  • to_entries / from_entries — tratar os pares chave-valor de um objeto como uma matriz para poder filtrá-los e reconstruí-los

Todos os exemplos pressupõem que o jq esteja instalado (apt install jq / brew install jq).

Noções básicas da construção de objetos

O recurso mais fundamental do jq é a construção de objetos: envolver expressões em {} para criar um novo objeto JSON. Você escolhe quais campos incluir e como chamá-los.

Sintaxe:

  • { newKey: .existingField } — renomeia um campo
  • { name, age } — forma abreviada quando a nova chave corresponde ao nome do campo
  • { total: (.price * .qty) } — calcula um valor diretamente na expressão

O trecho abaixo lê um JSON de produto e produz uma estrutura mais enxuta com um campo subtotal calculado.

#!/usr/bin/env bash
# Object construction: pick and rename fields
product='{
  "id": 42,
  "name": "Widget Pro",
  "price": 9.99,
  "qty": 3,
  "warehouse": "EU-West"
}'

echo "$product" | jq '{
  productId: .id,
  name,
  subtotal: (.price * .qty)
}'

Construindo objetos a partir de dados aninhados

O JSON do mundo real costuma ser aninhado. O jq permite acessar caminhos aninhados dentro de um construtor de objetos, achatando a estrutura ao mesmo tempo.

Use a notação de caminho com pontos dentro da expressão de valor do construtor:

  • { city: .address.city }
  • { lat: .location.coords.lat }

O exemplo abaixo recebe um registro de usuário profundamente aninhado e produz um resumo plano, adequado para uma linha de cabeçalho CSV ou para o corpo de uma requisição de API.

#!/usr/bin/env bash
user='{
  "id": "u-001",
  "profile": {
    "displayName": "Ada Lovelace",
    "contact": { "email": "ada@example.com", "phone": "+44-700" }
  },
  "plan": "pro"
}'

echo "$user" | jq '{
  id,
  name: .profile.displayName,
  email: .profile.contact.email,
  plan
}'

Transformando matrizes com map

map(expr) é o equivalente do jq a um for-each: aplica expr a cada elemento de uma matriz de entrada e retorna uma nova matriz com o mesmo comprimento.

Pontos principais:

  • map(expr) é uma abreviação de [.[] | expr]
  • A expressão interna pode ser qualquer filtro do jq — incluindo a construção de objetos
  • Encadeie com select() para filtrar antes de transformar

O trecho processa uma lista de pedidos, mantendo apenas os campos necessários para um manifesto de envio.

#!/usr/bin/env bash
orders='[
  {"orderId": 1, "customer": "Alice", "total": 42.50, "status": "shipped"},
  {"orderId": 2, "customer": "Bob",   "total": 18.00, "status": "pending"},
  {"orderId": 3, "customer": "Carol", "total": 99.99, "status": "shipped"}
]'

# Produce a shipping manifest: only shipped orders, slim fields
echo "$orders" | jq '[
  .[] | select(.status == "shipped") | {
    id: .orderId,
    recipient: .customer,
    amount: .total
  }
]'

map com campos calculados

Dentro de map, você pode calcular novos valores, converter tipos e combinar campos — não apenas copiá-los. Padrões comuns incluem:

  • Interpolação de strings: "\(.first) \(.last)"
  • Aritmética: (.price * 1.2 | round) para um acréscimo de 20%
  • Condicionais: if .score >= 90 then "A" else "B" end

O exemplo abaixo enriquece uma lista de funcionários adicionando um fullName calculado e um rótulo de seniority com base nos anos de experiência.

#!/usr/bin/env bash
staff='[
  {"first": "Grace", "last": "Hopper",  "years": 15},
  {"first": "Alan",  "last": "Turing",  "years": 4},
  {"first": "Linus", "last": "Torvalds","years": 9}
]'

echo "$staff" | jq 'map({
  fullName: "\(.first) \(.last)",
  years,
  seniority: (if .years >= 10 then "senior" elif .years >= 5 then "mid" else "junior" end)
})'

Entendendo to_entries

to_entries converte um objeto JSON em uma matriz de pares {key, value}. Isso permite usar operações de matriz (map, select, sort) nos campos de um objeto — algo que não é possível fazer diretamente em um objeto.

Exemplo de transformação:

  • Entrada: {"a": 1, "b": 2}
  • Saída: [{"key": "a", "value": 1}, {"key": "b", "value": 2}]

A operação inversa é from_entries, que transforma essa matriz novamente em um objeto. Juntas, elas formam o padrão to_entries | map(...) | from_entries para transformações no nível do objeto.

#!/usr/bin/env bash
# Demonstrate to_entries and from_entries
config='{"host": "db.local", "port": 5432, "ssl": true}'

echo "--- to_entries output ---"
echo "$config" | jq 'to_entries'

echo "--- round-trip back to object ---"
echo "$config" | jq 'to_entries | from_entries'

Filtrando chaves com to_entries

Um dos usos mais práticos de to_entries é filtrar dinamicamente quais chaves manter ou descartar com base no próprio nome da chave — algo que a construção de objetos não pode fazer quando você não conhece os nomes das chaves antecipadamente.

Padrão:

  • to_entries | map(select(.key | test("regex"))) | from_entries
  • to_entries | map(select(.key != "secret")) | from_entries

O trecho abaixo remove todas as chaves que começam com um sublinhado (campos internos/privados) antes de encaminhar um objeto de configuração para um serviço externo.

#!/usr/bin/env bash
raw_config='{
  "endpoint": "https://api.example.com",
  "timeout": 30,
  "_internalToken": "s3cr3t",
  "_debugMode": true,
  "retries": 3
}'

# Remove any key starting with underscore
echo "$raw_config" | jq '
  to_entries
  | map(select(.key | startswith("_") | not))
  | from_entries
'

Renomeando chaves dinamicamente com to_entries

A construção de objetos renomeia chaves quando você conhece seus nomes no momento da escrita. to_entries permite renomear chaves programaticamente — por exemplo, convertendo camelCase para snake_case ou adicionando um prefixo.

Dentro de map, você atualiza o campo .key de cada entrada e depois usa um pipe para from_entries:

  • map(.key |= gsub("(?<=[a-z])(?=[A-Z])"; "_") | .key |= ascii_downcase) — camelCase para snake_case
  • map(.key |= "app_" + .) — adiciona um prefixo a cada chave

O exemplo adiciona o prefixo APP_ a todos os nomes de variáveis de ambiente para criar um espaço de nomes antes de injetá-los em um contêiner.

#!/usr/bin/env bash
env_vars='{"host": "localhost", "port": "8080", "debug": "false"}'

# Add APP_ prefix and uppercase all keys
echo "$env_vars" | jq '
  to_entries
  | map({ key: ("APP_" + (.key | ascii_upcase)), value })
  | from_entries
'

with_entries: a abreviação conveniente

O padrão to_entries | map(...) | from_entries é tão comum que o jq fornece uma abreviação: with_entries(expr).

Ele é exatamente equivalente, mas mais conciso:

  • with_entries(.value |= . * 2) — duplica cada valor numérico
  • with_entries(select(.value != null)) — remove chaves com valores nulos
  • with_entries(.key |= ascii_upcase) — converte todas as chaves para maiúsculas

O trecho remove todas as chaves cujo valor é null ou uma string vazia — uma etapa comum de limpeza antes de enviar uma requisição PATCH para uma API REST.

#!/usr/bin/env bash
patch_body='{
  "name": "Mehmet",
  "email": "",
  "phone": null,
  "city": "Istanbul"
}'

# Drop empty/null fields before PATCH
cleaned=$(echo "$patch_body" | jq '
  with_entries(select(.value != null and .value != ""))
')

echo "Cleaned payload:"
echo "$cleaned"

# In practice you would pipe to curl:
# curl -s -X PATCH https://api.example.com/users/1 \
#   -H "Content-Type: application/json" \
#   -d "$cleaned"

Combinando map e construção de objetos em um fluxo

Transformações reais encadeiam várias operações do jq. Um fluxo típico para preparar uma carga de API pode:

  1. Filtrar a matriz de entrada com map(select(...))
  2. Reorganizar cada elemento com a construção de objetos
  3. Adicionar campos calculados
  4. Ordenar o resultado

O exemplo abaixo lê uma lista de métricas de servidores, mantém apenas os servidores com alto uso de CPU e produz uma carga compacta de alerta pronta para ser enviada por POST a um webhook.

#!/usr/bin/env bash
metrics='[
  {"host": "web-01", "cpu": 23, "mem": 60, "region": "eu"},
  {"host": "web-02", "cpu": 91, "mem": 88, "region": "eu"},
  {"host": "db-01",  "cpu": 78, "mem": 95, "region": "us"},
  {"host": "db-02",  "cpu": 12, "mem": 40, "region": "us"}
]'

alerts=$(echo "$metrics" | jq '[
  .[] | select(.cpu > 75 or .mem > 85) | {
    server: .host,
    region,
    severity: (if .cpu > 90 or .mem > 90 then "critical" else "warning" end),
    metrics: { cpu: .cpu, mem: .mem }
  }
] | sort_by(.severity)')

echo "$alerts"

Criando um novo objeto JSON a partir de várias fontes

O jq pode mesclar entradas e construir objetos provenientes de várias fontes JSON usando o operador de adição + e a vinculação de variáveis com as $var.

Padrões úteis:

  • obj1 + obj2 — mescla dois objetos (o lado direito prevalece em conflitos de chaves)
  • --argjson — passa um segundo documento JSON como variável
  • $ENV — lê variáveis de ambiente diretamente dentro do jq

O trecho mescla uma configuração básica com substituições específicas do ambiente — um padrão comum para gerenciar configurações de aplicações seguindo os princípios dos 12 fatores em scripts do shell.

#!/usr/bin/env bash
base_config='{
  "logLevel": "info",
  "timeout": 30,
  "retries": 3,
  "database": "postgres://db.local/app"
}'

env_overrides='{
  "logLevel": "debug",
  "database": "postgres://db.staging/app_staging"
}'

# Merge: overrides win on conflicts
merged=$(echo "$base_config" | jq --argjson overrides "$env_overrides" '. + $overrides')

echo "Merged config:"
echo "$merged"

Verificação de conhecimento: to_entries versus map

Você tem o seguinte objeto JSON e precisa remover todas as chaves cujo valor é menor que 0, produzindo um novo objeto apenas com valores não negativos. Qual expressão do jq realiza isso corretamente?

Entrada: {"a": 10, "b": -3, "c": 0, "d": 5}

Recapitulação da lição: transformando JSON com jq

Você aprendeu as técnicas essenciais para reorganizar JSON com jq:

  • Construção de objetos {} — cria novos objetos escolhendo, renomeando e calculando campos a partir de uma entrada
  • map(expr) — aplica qualquer transformação a cada elemento de uma matriz, incluindo a construção de objetos aninhados e select() para filtragem
  • to_entries / from_entries — converte um objeto em uma matriz de pares {key, value}, permitindo operações de matriz nas chaves e nos valores, e depois converte novamente
  • with_entries(expr) — a abreviação concisa para o fluxo completo to_entries → map → from_entries
  • Mesclagem de objetos com + e --argjson para cargas provenientes de várias fontes

Esses blocos básicos se combinam: filtre com select, reorganize com a construção de objetos, enriqueça com campos calculados e encadeie tudo em uma única expressão jq legível. Dominar esses padrões significa que você pode manipular praticamente qualquer carga JSON diretamente no shell, sem escrever um script dedicado em Python ou Node.

Perguntas Frequentes

A aula “Transformação e criação de objetos JSON com jq” é grátis?

Sim — o texto completo de “Transformação e criação de objetos JSON com jq” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de DevOps Bootcamp, atualize para CoddyKit PRO. O curso de DevOps Bootcamp inclui 4 aulas no total.

O que vou aprender em “Transformação e criação de objetos JSON com jq”?

Remodele dados com map, to_entries e construção de objetos para produzir novos conteúdos JSON. Você pratica DevOps Bootcamp com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar DevOps Bootcamp?

Nenhuma experiência prévia é necessária. DevOps Bootcamp no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 2 de 4.

Quanto tempo leva a aula “Transformação e criação de objetos JSON com jq”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de DevOps Bootcamp?

Sim. Cada aula de DevOps Bootcamp inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Filtragem e seleção de JSON com pipelines do jq
  2. Transformação e criação de objetos JSON com jq
  3. Consumo conjunto de APIs REST com curl e jq
  4. Edição de arquivos de configuração YAML com yq
← Voltar para DevOps Bootcamp