Trabalhando com JSON aninhado: achatando, consultando e transformando dados
O JSON se aninha naturalmente — objetos dentro de objetos, arrays dentro de objetos, objetos dentro de arrays — porque é assim que os programas modelam dados. Planilhas, arquivos CSV e tabelas SQL não se aninham de forma alguma; são estritamente bidimensionais, linhas e colunas. A lacuna entre esses dois mundos é onde entra o 'achatamento' (flattening), e saber quando achatar e quando deixar a estrutura em paz é a maior parte do que torna o JSON aninhado administrável.
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 dentro não tem um mapeamento óbvio de linha/coluna — qual campo vira coluna, e o que acontece com um campo que se repete por item do array? Colar JSON aninhado num conversor 'JSON para CSV' ingênuo ou no importador de JSON do Excel ou descarta os campos aninhados inteiramente ou os despeja numa única célula como um blob stringificado — e ambos os desfechos jogam fora exatamente a estrutura sobre a qual você gostaria de 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 realmente significa
Achatar transforma uma estrutura aninhada num objeto de nível único em que cada caminho aninhado se torna uma chave, tipicamente 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`), transformando uma lista num conjunto de chaves individualmente endereçáveis. O resultado não tem aninhamento algum — todo valor é uma string, número ou booleano simples, e toda chave identifica exclusivamente exatamente um valor folha do documento original.
Essa propriedade — uma chave por valor folha, sem aninhamento — é exatamente o que uma coluna de planilha, uma linha SQL ou um simples armazenamento chave/valor precisa.
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 direto e sem ambiguidade para um único valor original — trivialmente utilizáveis como seis colunas de planilha ou seis colunas numa única linha SQL.
Quando achatar vs. quando manter o aninhamento
Achate quando o destino é genuinamente 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 índice por item é uma troca razoável.
Mantenha o aninhamento, ou reestruture em vez de achatar, quando um array contém objetos completos cuja contagem varia por registro — um array `orders` em que cada usuário tem um número diferente de pedidos, cada um com vários campos próprios. Achatá-lo no lugar ou produz um conjunto de colunas irregular e diferente por registro (`orders.0.total`, `orders.1.total`, ... `orders.14.total` para o seu maior cliente) ou desiste e colapsa o array inteiro numa única célula de JSON stringificado, o que derrota todo o propósito do achatamento. A jogada melhor para arrays de objetos é a normalização relacional clássica: extraia o array para sua própria tabela/planilha com uma chave estrangeira de volta ao registro pai, em vez de tentar forçá-lo em colunas na linha pai. É exatamente isso que a ferramenta JSON to Table do JSONForge faz automaticamente — 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 por índice.
Acesso por caminho: consultando sem achatar tudo
Às vezes você não precisa achatar um documento inteiro — só precisa de um valor de dentro de uma estrutura profundamente aninhada. A notação de caminho por ponto (`user.address.city`) ou uma expressão estilo JSONPath (`$.user.address.city`, `$.roles[0]`) permite endereçar diretamente um único valor aninhado — a mesma ideia por trás do achatamento, aplicada a uma consulta em vez do documento inteiro. É o que alimenta `lodash.get(obj, 'user.address.city')`, a interpolação de variáveis da maioria dos motores de template e as ferramentas de consulta JSON em geral.
Na prática, as duas técnicas se combinam: a ferramenta JSON Flatten do JSONForge aplica essa transformação de caminho por ponto num documento inteiro de uma vez, transformando cada valor aninhado numa chave plana e endereçável — útil sempre que o destino é uma planilha, um armazenamento chave/valor simples ou qualquer ferramenta que não consiga percorrer estruturas aninhadas nativamente.
FAQ
- Qual a diferença entre achatar e simplesmente stringificar campos aninhados?
- Achatar transforma cada valor aninhado em sua própria chave escalar de nível superior, então cada valor permanece independentemente consultável, ordenável e filtrável. 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 antes analisar a string de novo. O achatamento preserva a consultabilidade; stringificar apenas adia o problema.
- Como os arrays são representados ao achatar JSON?
- A convenção padrão é anexar o índice do array ao caminho, então `roles: ["admin", "editor"]` se torna `roles.0: "admin"` e `roles.1: "editor"`. Isso funciona de forma limpa para listas curtas e razoavelmente fixas de escalares, mas produz um conjunto irregular e sempre crescente de chaves para arrays cujo comprimento varia muito entre registros — nesse caso, uma tabela relacionada separada costuma ser uma escolha melhor do que chaves achatadas por índice.
- Um objeto JSON achatado pode ser convertido de volta para sua forma aninhada original?
- Sim — o 'desachatamento' (unflatten) reverte o processo dividindo cada chave de caminho por ponto de volta em suas partes e reconstruindo os objetos e arrays aninhados a partir delas, desde que a convenção de separador tenha sido aplicada de forma consistente e nenhuma chave original contenha um ponto literal por acaso.
- 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.