Trabalhando com JSON aninhado: achatando, consultando e transformando dados
O JSON aninha objetos dentro de objetos, arrays dentro de objetos e objetos dentro de arrays, porque é assim que os programas modelam dados. Planilhas, arquivos CSV e tabelas SQL não aninham nada; têm duas dimensões, linhas e colunas. O achatamento (flattening) faz a ponte entre os dois mundos, e quase todo o trabalho com JSON aninhado está em saber quando achatar e quando deixar a estrutura como está.
Por que o JSON profundamente aninhado resiste a planilhas e SQL
Um objeto JSON com três níveis de aninhamento e um array enterrado não tem um mapeamento óbvio de linha/coluna. Qual campo vira coluna, e o que acontece com um campo que se repete em cada item do array? Cole JSON aninhado num conversor 'JSON para CSV' ingênuo ou no importador de JSON do Excel, e ele descarta os campos aninhados ou os despeja numa única célula como blob stringificado. Os dois desfechos jogam fora a estrutura sobre a qual você queria filtrar, ordenar ou consultar.
Isso não é tanto uma falha de ferramenta quanto um descompasso representacional real: o JSON aninhado codifica uma árvore, e uma planilha ou tabela SQL codifica uma lista plana de registros. Ir de um ao outro exige uma decisão explícita sobre como lidar com esse descompasso, não apenas uma conversão de formato.
O que achatamento significa
Achatar transforma uma estrutura aninhada num objeto de nível único em que cada caminho aninhado vira uma chave, unida por ponto (`user.address.city`) ou escrita em notação de colchetes (`user[address][city]`). Itens de array recebem um índice no caminho (`roles.0`, `roles.1`), e a lista vira um conjunto de chaves endereçáveis uma a uma. O resultado não tem aninhamento: todo valor é uma string, número ou booleano simples, e cada chave identifica um único valor folha do documento original.
Uma coluna de planilha, uma linha SQL ou um armazenamento chave/valor simples precisam dessa propriedade: uma chave por valor folha, sem aninhamento.
Um exemplo prático
Tome um registro de usuário aninhado típico, com um objeto de endereço e um array de strings de papéis.
{
"user": {
"id": 42,
"name": "Ada Lovelace",
"address": {
"city": "London",
"postcode": "W1"
},
"roles": ["admin", "editor"]
}
}{
"user.id": 42,
"user.name": "Ada Lovelace",
"user.address.city": "London",
"user.address.postcode": "W1",
"user.roles.0": "admin",
"user.roles.1": "editor"
}Seis chaves, zero aninhamento, e cada uma é um caminho sem ambiguidade para um único valor original. Você pode usá-las como seis colunas de planilha ou seis colunas numa única linha SQL.
Quando achatar vs. quando manter o aninhamento
Achate quando o destino é tabular (um export CSV, uma planilha, uma única linha de tabela SQL, uma ferramenta de análise que só entende colunas planas) e quando os arrays são listas curtas de escalares (como `roles` acima), em que uma chave numerada por item ainda é uma troca razoável.
Mantenha o aninhamento, ou reestruture, quando um array contém objetos completos cuja quantidade varia por registro. Pense num array `orders` em que cada usuário tem um número diferente de pedidos, cada um com vários campos. Achatar isso no lugar dá a cada registro um conjunto de colunas irregular e diferente (`orders.0.total`, `orders.1.total`, ... `orders.14.total` para o seu maior cliente) ou colapsa o array inteiro numa célula de JSON stringificado, e o achatamento perde o sentido. Para arrays de objetos, use a normalização relacional clássica: leve o array para sua própria tabela/planilha com uma chave estrangeira apontando para o registro pai. A ferramenta JSON to Table do JSONForge faz isso por você. Ela achata campos escalares em colunas da tabela e separa arrays de objetos em suas próprias tabelas relacionadas, em vez de amassá-los em colunas numeradas.
Acesso por caminho: consultando sem achatar tudo
Às vezes você precisa de um único valor de dentro de uma estrutura profundamente aninhada, não de um documento achatado. A notação de caminho por ponto (`user.address.city`) ou uma expressão estilo JSONPath (`$.user.address.city`, `$.roles[0]`) endereça um valor aninhado diretamente. O achatamento aplica a mesma ideia ao documento inteiro; um caminho a aplica a uma consulta. `lodash.get(obj, 'user.address.city')`, a interpolação de variáveis da maioria dos motores de template e as ferramentas de consulta JSON funcionam assim.
As duas técnicas se complementam. A ferramenta JSON Flatten do JSONForge aplica a transformação de caminho por ponto ao documento inteiro de uma vez e transforma cada valor aninhado numa chave plana. Use-a quando o destino for uma planilha, um armazenamento chave/valor simples ou uma ferramenta que não consiga percorrer estruturas aninhadas.
FAQ
- Qual a diferença entre achatar e stringificar campos aninhados?
- Achatar transforma cada valor aninhado em sua própria chave escalar de nível superior, então você continua podendo consultar, ordenar e filtrar cada valor. Stringificar um campo aninhado o colapsa num único blob de texto opaco. Você pode exibi-lo, mas não consegue filtrar por um valor interno nem ordenar por ele sem analisar a string de novo. Stringificar adia o problema que o achatamento resolve.
- Como os arrays são representados ao achatar JSON?
- A convenção padrão anexa o índice do array ao caminho, então `roles: ["admin", "editor"]` se torna `roles.0: "admin"` e `roles.1: "editor"`. Isso funciona bem para listas curtas e mais ou menos fixas de escalares. Para arrays cujo tamanho varia muito entre registros, o resultado é um conjunto de chaves irregular e crescente, e uma tabela relacionada separada se encaixa melhor.
- Um objeto JSON achatado pode ser convertido de volta para sua forma aninhada original?
- Sim. O 'desachatamento' (unflatten) divide cada chave de caminho por ponto em suas partes e reconstrói os objetos e arrays aninhados, desde que você tenha aplicado a convenção de separador de forma consistente e nenhuma chave original contenha um ponto literal.
- A notação por ponto é a única forma de representar uma chave achatada?
- Não. A notação por ponto (`user.address.city`) é a mais comum porque espelha como você acessaria o valor em JavaScript ou Python, mas a notação por colchetes (`user[address][city]`) e chaves unidas por underscore (`user_address_city`) também são usadas, especialmente por ferramentas voltadas a ambientes em que pontos em nomes de colunas são inconvenientes (alguns dialetos SQL, certas ferramentas de planilha). A convenção importa menos do que aplicá-la de forma consistente no documento inteiro.
Experimente estas ferramentas
Artigos relacionados
O que é JSON? Um guia completo para iniciantes →
JSON (JavaScript Object Notation) é um formato leve de troca de dados, fácil de ler por humanos e de analisar por máquinas. Aprenda a sintaxe, os tipos de dados e a estrutura que sustentam as APIs modernas.
A história do JSON: de 2000 a padrão da indústria →
Acompanhe o JSON desde a ideia de Douglas Crockford em 2001, passando pela adoção pelo Yahoo, até se tornar o padrão ECMA-404 que sustenta 90% das APIs modernas.
O guia completo do JSON Schema (Draft 7) →
O JSON Schema é o padrão para descrever e validar a estrutura de JSON. Aprenda as palavras-chave essenciais, construa um schema real de API e aplique as melhores práticas.