JSON para Excel: quatro abordagens e onde cada uma perde fidelidade
Resumo: Estruturas aninhadas, campos inconsistentes e arrays de arrays são onde a conversão de JSON para planilha quebra. Quatro abordagens ordenadas por tempo até o resultado, cada uma com seus trade-offs.

Resumo da ópera: um array plano de objetos ou um objeto envolvendo um array convertem mais rápido pela ferramenta online; use Power Query quando os dados forem atualizados semanalmente, pandas quando houver muitos campos a limpar e um script Node apenas quando a conversão precisar entrar em um pipeline — mas decida o que significa "uma linha" antes de tocar em dados aninhados ou chaves inconsistentes.
A conversão em si não é difícil; o difícil é descobrir depois que números viraram texto e que vários níveis de aninhamento colapsaram em um. Leia a estrutura dos dados antes de escolher um método e você economiza um retrabalho.
1. Primeiro, descubra que tipo de JSON você tem
Abra o arquivo e olhe o nível mais externo:
| Estrutura | Formato | Dificuldade de conversão |
|---|---|---|
| Array plano de objetos | [{"a":1,"b":2},{...}] |
Mais fácil — uma linha por registro |
| Objeto envolvendo um array | {"data":[{...}],"total":100} |
Fácil — pegue o nível data |
| Objetos aninhados | {"user":{"name":"x"}} |
Médio — decida entre achatar ou unir em uma string |
| Arrays de arrays | {"tags":["a","b"]} |
Penoso — não cabe em uma linha, exige divisão de tabela |
| Chaves inconsistentes | Cada registro tem campos diferentes | Penoso — as colunas ficam em grande parte vazias |
As duas primeiras convertem direto com quase 100% de sucesso; para as três últimas, decida primeiro o que significa "uma linha", caso contrário a planilha resultante fica inutilizável.
2. Abordagem 1: ferramenta online (1 minuto)
Abra JSON para tabela, cole os dados → escolha o delimitador e o cabeçalho → exporte CSV → abra no Excel. Adequado para algumas dezenas a alguns milhares de linhas de dados bem estruturados.
Três coisas às quais você precisa ficar atento:
- Você recebe CSV, não xlsx. Quando o Excel abre um CSV, ele adivinha a codificação pela localidade do sistema, então texto em chinês pode virar mojibake. Usar "Dados → De Texto/CSV" e selecionar UTF-8 explicitamente é mais confiável.
- Identificadores que começam com
0perdem os zeros."007"é texto no CSV, mas o Excel o converte automaticamente para o número 7. Defina essa coluna como texto durante a importação, ou adicione um prefixo a ela no JSON. - Números longos viram notação científica. Documentos de identidade e números de pedido com mais de 15 dígitos perdem precisão; esses campos já deveriam ser strings no JSON e precisam permanecer em formato de texto após a importação.
3. Abordagem 2: Power Query nativo do Excel (reutilizável)
Quando seus dados são atualizados toda semana, use o Power Query nativo do Excel: configure uma vez e depois só clique em "Atualizar":
- "Dados" → "Obter dados" → "De arquivo" → "De JSON";
- Após selecionar o arquivo, você cai no editor do Power Query, onde vê estruturas
List/Record; - Clique no ícone de expansão do lado direito de um cabeçalho de coluna para expandir campos aninhados nível por nível;
- Quando os nomes e tipos das colunas estiverem certos, "Fechar e carregar".
A vantagem é que o aninhamento pode ser expandido em várias colunas camada por camada, e os tipos podem ser atribuídos manualmente; o preço é que a primeira configuração exige entender a diferença entre List e Record — List é um array, Record é um objeto, e eles se expandem em direções diferentes.
4. Abordagem 3: Python + pandas (muitos campos, precisa de limpeza)
import pandas as pd
# Objeto envolvendo um array: primeiro chegue ao nível da lista
rows = pd.read_json('data.json')['data']
# Expanda campos aninhados em várias colunas
frame = pd.json_normalize(rows, sep='_')
frame.to_excel('out.xlsx', index=False)
O parâmetro-chave de json_normalize é sep, que determina o estilo de nomeação das colunas após expandir campos aninhados; user_name é mais fácil de usar no Excel do que user.name. Arrays de arrays (como tags) precisam de uma etapa extra de explode:
frame = frame.explode('tags')
Essa etapa divide uma linha em várias, a única forma de preservar uma relação um-para-muitos — ao custo de duplicar os demais campos.
5. Abordagem 4: um script Node (quando precisa entrar em um pipeline)
import { readFileSync, writeFileSync } from 'node:fs';
const rows = JSON.parse(readFileSync('data.json', 'utf8'));
const headers = [...new Set(rows.flatMap((row) => Object.keys(row)))];
const escapeCell = (value) => `"${String(value ?? '').replaceAll('"', '""')}"`;
const lines = [
headers.join(','),
...rows.map((row) => headers.map((key) => escapeCell(row[key])).join(',')),
];
writeFileSync('out.csv', '\uFEFF' + lines.join('\n'), 'utf8');
Dois detalhes que você não deve pular: escreva \uFEFF (um BOM) no início para que o Excel reconheça UTF-8, e escape aspas duplas dentro das células como "", caso contrário as colunas desalinham.
6. Três coisas que a conversão sempre perde
| Item perdido | Sintoma | Remédio |
|---|---|---|
| Informação de tipo | Números e booleanos viram texto ou TRUE/FALSE |
Defina os tipos das colunas manualmente após importar, ou especifique-os no Power Query |
| Níveis de aninhamento | Campos profundos colapsam em [object Object] |
Use json_normalize ou expanda nível por nível — nunca String(obj) |
| Relações um-para-muitos | Arrays são enfiados em uma única célula | Divida linhas com explode, ou construa uma tabela relacionada separada |
Além disso, null e "campo ausente" parecem iguais em uma planilha (ambos são células vazias), mas significam coisas diferentes no domínio de negócio. Quando precisar distingui-los, converta explicitamente null para a string "null" no JSON, ou adicione uma coluna marcadora _has_field.
7. Verificação posterior: não olhe só a primeira linha
Após a conversão, inspecione pelo menos três coisas:
- Contagem de registros: o número de linhas do CSV deve ser igual ao comprimento do array + 1 (o cabeçalho); uma linha a menos geralmente significa que a quebra de linha final foi engolida;
- A coluna com maior taxa de nulos: muitas células vazias indicam nomes de chave inconsistentes — volte e verifique se o JSON original usa duas grafias (
userIdeuser_id); - A linha mais longa: arrays aninhados costumam cair ali; confirme que nada foi truncado.
Quando precisar da operação inversa (Excel/CSV de volta para JSON), use CSV para JSON, e lembre que o cabeçalho é tratado como os nomes das chaves — mudar o cabeçalho é mudar os nomes dos campos.
Perguntas frequentes
Como escolher entre a ferramenta online, o Power Query e o pandas?
Use a ferramenta online para algumas dezenas a alguns milhares de linhas de dados bem estruturados que você converte uma vez. Use o Power Query quando os dados forem atualizados toda semana, já que ele é configurado uma vez e atualizado com um clique. Use pandas com json_normalize quando houver muitos campos a limpar, e um script Node quando a conversão precisar entrar em um pipeline.
Por que o texto em chinês vira mojibake em um CSV?
A exportação é CSV, não xlsx, e o Excel adivinha a codificação pela localidade do sistema, então UTF-8 sem BOM mostra mojibake. Escreva um BOM \uFEFF no início do arquivo, ou abra-o por "Dados → De Texto/CSV" e selecione UTF-8 explicitamente.
Objetos aninhados devem ser achatados ou divididos em linhas extras?
Ache-os nível por nível em vez de colá-los como strings: o Power Query expande campos aninhados em colunas, e json_normalize com sep faz o mesmo no pandas. Arrays de arrays precisam de uma etapa extra de explode que divide uma linha em várias. Passar um objeto profundo para String(obj) só produz [object Object].