Skip to content
Back to Blog
jsonjavascriptformattingdeveloper-tools

Como Formatar JSON em JavaScript (Pretty Print)

JSON.stringify com o argumento space é a solução de uma linha que a maioria dos desenvolvedores usa, mas tem arestas afiadas em relação a replacers, referências circulares e minificação. Este guia aborda o caminho do código e a alternativa sem instalação.

SZ
Founder, Molixa
13 min read
Compartilhar
Como Formatar JSON em JavaScript (Pretty Print)
Table of contents8 sections

A maneira mais rápida de formatar JSON em JavaScript é JSON.stringify(value, null, 2). O terceiro argumento, o parâmetro space, instrui o motor a indentar cada nível aninhado, transformando uma linha densa em uma saída legível e bem formatada. Essa linha única cobre a maioria dos casos, mas falha em referências circulares, remove funções e undefined silenciosamente, e não oferece controle sobre quais campos são incluídos. Este guia percorre todo o caminho do código e as arestas afiadas que todo tutorial ignora.

Se você só precisa de uma saída limpa uma vez e não quer escrever um script descartável, pode colar o texto bruto em um formatador JSON online gratuito e copiar o resultado. Para tudo que precisa acontecer dentro do seu código, as seções abaixo cobrem os argumentos, as pegadinhas e os padrões que realmente importam em produção.

Como formatar JSON em JavaScript com JSON.stringify#

JSON.stringify() recebe três argumentos: o valor a ser serializado, um replacer opcional e um space opcional. Para uma formatação bonita, você pula o replacer com null e passa um número ou string como space.

const user = { name: "Ada", roles: ["admin", "editor"], active: true };

// Compacto (padrão), tudo em uma linha
JSON.stringify(user);
// {"name":"Ada","roles":["admin","editor"],"active":true}

// Formatado com indentação de 2 espaços
JSON.stringify(user, null, 2);
// {
//   "name": "Ada",
//   "roles": [
//     "admin",
//     "editor"
//   ],
//   "active": true
// }

O argumento space é o que faz o trabalho. Passe um número de 1 a 10 para aquela quantidade de espaços de indentação por nível, ou passe uma string (como "\t") para indentar com essa string.

Números acima de 10 são limitados a 10. JSON.stringify(obj, null, 50) se comporta exatamente como JSON.stringify(obj, null, 10), então não espere indentação mais profunda passando um número maior.

O parâmetro space: números vs strings#

O argumento space aceita dois tipos, e o tipo muda o estilo da saída:

Valor de spaceResultadoUso comum
2Dois espaços por nívelJavaScript, JSON config, maioria dos ecossistemas web
4Quatro espaços por nívelFerramentas Python, algumas saídas Java/.NET
"\t"Uma tabulação por nívelRepositórios que usam indentação com tab
0, null ou omitidoSem formatação, linha únicaPayloads de API, armazenamento, transferência de rede

Uma string space permite fazer coisas que um número não consegue. Passe " " (dois espaços) para o mesmo efeito que 2, ou passe algo visual como "--" para depurar a profundidade de aninhamento. Apenas os primeiros 10 caracteres de uma string space são usados.

Por que 2 vs 4 espaços realmente importa#

Isso não é frescura. A largura da indentação é uma convenção do ecossistema, e combiná-la mantém sua saída consistente com as ferramentas que a lerão em seguida.

  • 2 espaços é o padrão de facto no mundo JavaScript e Node. Prettier usa 2 por padrão, o package.json do npm usa 2, e a maioria dos arquivos de configuração JSON que você vai mexer (tsconfig.json, .eslintrc.json) seguem o mesmo.
  • 4 espaços aparece onde a linguagem ao redor usa 4, principalmente o json.dumps(obj, indent=4) do Python. Se um arquivo JSON fica ao lado de código Python ou é gerado por um serviço Python, 4 mantém o alinhamento visual.
  • Tabs aparecem em repositórios com guia de estilo baseado em tab. A vantagem é que cada desenvolvedor pode definir sua própria largura de exibição da tab.

Se seu projeto usa Prettier ou um formatador no commit, use a mesma configuração para não brigar com o auto-formatador. Em caso de dúvida, use 2.

Usando uma Função de Substituição para Controlar a Saída#

O segundo argumento, replacer, é o recurso menos usado do JSON.stringify. Ele controla quais propriedades são serializadas e como seus valores são transformados. Aceita um array ou uma função.

Substituição como lista de permissões (array)#

Passe um array com os nomes das propriedades e apenas essas chaves serão mantidas. Esta é a forma mais limpa de remover campos sensíveis ou desnecessários antes de registrar ou enviar dados.

const account = {
  id: 42,
  email: "[email protected]",
  passwordHash: "$2b$10$...",
  sessionToken: "abc123",
};

// Apenas id e email aparecem na saída
JSON.stringify(account, ["id", "email"], 2);
// {
//   "id": 42,
//   "email": "[email protected]"
// }

A lista de permissões se aplica em todos os níveis do objeto, então uma chave chamada id é mantida onde quer que apareça na árvore. Isso é útil para estruturas uniformes, mas pode ser problemático em árvores onde o mesmo nome de chave significa coisas diferentes em profundidades diferentes.

Substituição como função de transformação#

Passe uma função e ela será executada para cada par chave/valor. Retorne o valor que deseja serializar, retorne undefined para remover a chave ou transforme em tempo real. A função recebe a chave e o valor, e this é vinculado ao objeto que contém a chave.

const order = { total: 19.99, secret: "hide-me", createdAt: new Date() };

const json = JSON.stringify(order, (key, value) => {
  if (key === "secret") return undefined;        // remove o campo
  if (typeof value === "number") return value.toFixed(2); // formata números
  return value;
}, 2);

Atenção à ordem de chamada: o substituidor é invocado primeiro com uma chave vazia e o objeto inteiro, depois para cada propriedade. Se você transformar valores cegamente sem verificar a chave, pode acidentalmente modificar a raiz.

Uma alternativa mais limpa para controle por objeto é o método toJSON(). Qualquer objeto com um método toJSON() (como Date, que por isso serializa datas como strings ISO) controla sua própria forma serializada antes mesmo do substituidor vê-lo.

Corrigindo o Erro de Tipo de Referência Circular#

Este é o erro que todo tutorial básico ignora, e que vai te parar de verdade. Se um objeto referencia a si mesmo, diretamente ou através de uma cadeia, JSON.stringify lança:

TypeError: Converting circular structure to JSON

Isso acontece constantemente com nós DOM, entidades ORM que ligam de volta ao pai, objetos de evento e qualquer dado em formato de grafo.

const node = { name: "root" };
node.self = node; // circular

JSON.stringify(node, null, 2); // TypeError: Converting circular structure to JSON

A correção é um replacer que rastreia objetos já vistos e pula repetições:

function safeStringify(value, space = 2) {
  const seen = new WeakSet();
  return JSON.stringify(value, (key, val) => {
    if (typeof val === "object" && val !== null) {
      if (seen.has(val)) return "[Circular]";
      seen.add(val);
    }
    return val;
  }, space);
}

safeStringify(node);
// {
//   "name": "root",
//   "self": "[Circular]"
// }

Um WeakSet é a ferramenta certa aqui porque não impede a coleta de lixo dos objetos que rastreia. Se você estiver em um Node recente ou navegador moderno, o global structuredClone também lançará erro em dados circulares, então um replacer com conjunto de vistos continua sendo a solução prática para serialização.

Valores que desaparecem silenciosamente#

JSON.stringify não apenas lança erro em dados circulares. Ele também remove ou altera silenciosamente vários tipos de valor, o que leva a bugs confusos onde um campo "desaparece".

  • Funções e undefined são omitidos completamente de objetos, e se tornam null dentro de arrays.
  • NaN e Infinity serializam para null.
  • BigInt lança um TypeError. Você deve convertê-lo para string ou número primeiro.
  • Symbol chaves e valores são ignorados.
  • Date se torna uma string ISO (através do seu toJSON), então não faz ida e volta para um Date ao fazer parse.

Se uma propriedade está faltando na sua saída, um desses é quase sempre o motivo.

Como Minificar JSON em JavaScript#

Minificar é o inverso de pretty-print: remover todos os espaços em branco para obter o payload mais compacto possível. Você minifica chamando JSON.stringify sem o argumento space (ou com 0).

const data = { name: "Ada", roles: ["admin", "editor"] };

JSON.stringify(data);
// {"name":"Ada","roles":["admin","editor"]}

Para converter de formatado para minificado, faça o parse da string formatada de volta para um objeto e stringifique novamente sem space:

const pretty = `{
  "name": "Ada",
  "active": true
}`;

const minified = JSON.stringify(JSON.parse(pretty));
// {"name":"Ada","active":true}

Esse padrão de JSON.parse seguido de JSON.stringify também é a maneira mais simples de reformatar JSON não confiável ou mal indentado: o parse normaliza e o stringify reemite com o espaçamento que você escolher. O problema é que JSON.parse é rigoroso, então vírgulas finais, aspas simples, comentários ou uma resposta HTML acidental lançarão um SyntaxError antes que você consiga formatar qualquer coisa.

Quando Pular o Código Completamente#

Escrever JSON.stringify é a escolha certa quando a formatação acontece dentro da sua aplicação: logging, construção de arquivos de configuração em tempo de execução, normalização de uma resposta de API. Mas muitas vezes você só tem um bloco de JSON feio na sua área de transferência e precisa lê-lo agora. Abrir um REPL, fazer parse, stringify e copiar de volta é mais lento do que deveria ser.

Para isso, um formatador baseado em navegador é mais rápido e seguro:

  • Ele valida enquanto formata, então JSON malformado recebe um erro claro com linha e coluna em vez de um throw enigmático.
  • Você alterna entre indentação de 2 espaços, 4 espaços, tabulação ou saída minificada sem reescrever código.
  • Ele lida com cargas enormes que poluiriam seu console.
  • Os bons rodam inteiramente no lado do cliente, então seus dados nunca saem do navegador.

O formatador e validador JSON da Molixa faz exatamente isso: cole, obtenha saída formatada e validada, alterne a indentação e copie. Se você quiser o caso mais profundo para manter um no seu kit de ferramentas diário, nosso artigo sobre por que um formatador JSON é uma ferramenta diária para desenvolvedores detalha o fluxo de trabalho. E quando a saída que você está formatando precisa se tornar código tipado, o guia de JSON para interface TypeScript mostra como transformar uma carga limpa em interfaces reais.

Como Criar uma Função Reutilizável de Formatação JSON#

Se você formata JSON em vários lugares, encapsule o padrão seguro uma vez e reutilize em vez de espalhar JSON.stringify(obj, null, 2) pelo código. Siga estas etapas para criar um helper que imprime de forma bonita, minifica, lida com tabulações e nunca lança exceções.

Etapa 1: Configurar um conjunto de objetos já vistos para capturar referências circulares#

Comece com um WeakSet para rastrear objetos que você já serializou. Um WeakSet é a escolha certa porque mantém referências fracas e não impede a coleta de lixo desses objetos.

function formatJSON(value, { indent = 2, safe = true } = {}) {
  const seen = new WeakSet();
  // replacer vem a seguir
}

O objeto de opções com valores padrão (indent = 2, safe = true) significa que uma chamada simples formatJSON(data) faz o esperado: saída com 2 espaços e segura contra referências circulares.

Etapa 2: Escrever um replacer que lida com tipos não suportados#

Adicione um replacer que retorna um placeholder para objetos repetidos e converte BigInt para string para que não lance erro. Esta é a mesma correção de referência circular de antes, mais a proteção para BigInt.

const replacer = safe
  ? (key, val) => {
      if (typeof val === "object" && val !== null) {
        if (seen.has(val)) return "[Circular]";
        seen.add(val);
      }
      if (typeof val === "bigint") return val.toString();
      return val;
    }
  : null;

Quando safe é false, o replacer é null, então você obtém o comportamento padrão de JSON.stringify para casos onde sabe que os dados estão limpos e deseja máxima velocidade.

Etapa 3: Stringify dentro de um try/catch para nunca lançar exceções#

Envolva a chamada JSON.stringify para que qualquer erro de serialização restante retorne uma mensagem legível em vez de quebrar seu caminho de log ou renderização.

  try {
    return JSON.stringify(value, replacer, indent);
  } catch (err) {
    return `// Não foi possível formatar: ${err.message}`;
  }
}

Etapa 4: Chamar com a indentação necessária#

O mesmo helper agora cobre todos os modos de formatação através da opção indent.

formatJSON(someApiResponse);             // 2 espaços, seguro
formatJSON(config, { indent: "\t" });    // indentado com tab
formatJSON(payload, { indent: 0 });      // minificado

Coloque isso em um arquivo utils e você terá impressão bonita, minificação, indentação com tab, e as armadilhas de referência circular e BigInt resolvidas em um só lugar.

Formatando JSON em JavaScript: A Versão Resumida#

Para formatar JSON em JavaScript, use JSON.stringify(valor, null, 2) primeiro. É a ferramenta certa nove em cada dez vezes. Lembre-se das três coisas que os tutoriais ignoram: um array replacer é uma lista de permissões limpa para remover campos sensíveis, um replacer com conjunto de vistos corrige o TypeError de referência circular, e vários tipos de valor (funções, undefined, BigInt, NaN) são descartados ou geram erro em vez de serializar.

Quando o JSON está na sua área de transferência em vez do código, pule o script e cole-o em um formatador e validador de JSON para formatação instantânea, validação e minificação com um clique. Combine sua indentação (geralmente 2 espaços) com seu ecossistema, mantenha o auxiliar reutilizável à mão e você nunca mais vai lutar com JSON ilegível.

Perguntas Frequentes#

Como faço para formatar JSON com indentação em JavaScript? Use JSON.stringify(value, null, 2). O terceiro argumento é o parâmetro space: passar 2 indenta cada nível aninhado com dois espaços, produzindo uma saída legível. Passe 4 para quatro espaços ou "\t" para indentação com tabulação.

O que o terceiro argumento do JSON.stringify faz? O terceiro argumento é space, que controla a indentação. Um número de 1 a 10 indenta esse número de espaços por nível, e uma string usa essa string como indentação (apenas os primeiros 10 caracteres são considerados). Omiti-lo, ou passar 0 ou null, produz saída compacta em uma única linha sem formatação.

Por que o JSON.stringify lança "Converting circular structure to JSON"? Porque um objeto referencia a si mesmo diretamente ou através de uma cadeia, e o JSON não tem como representar esse ciclo. Corrija com uma função de substituição que rastreia objetos já vistos em um WeakSet e retorna um placeholder como "[Circular]" para repetições, em vez de deixar o motor recursar para sempre.

Como minificar JSON em JavaScript? Chame JSON.stringify(value) sem o argumento space, ou passe 0. Para minificar uma string formatada existente, execute JSON.stringify(JSON.parse(prettyString)), que a analisa de volta para um objeto e a reemite sem espaços em branco.

Por que algumas propriedades desaparecem quando converto um objeto para string? JSON.stringify descarta silenciosamente funções, valores undefined e chaves Symbol de objetos, e converte NaN e Infinity para null. Valores BigInt lançam um TypeError diretamente. Se um campo estiver faltando na saída, quase sempre é um desses tipos não suportados.

Devo usar 2 ou 4 espaços para formatar JSON? Combine com seu ecossistema. JavaScript e Node usam 2 espaços por padrão (Prettier, npm, tsconfig.json), enquanto ferramentas Python geralmente usam 4. Se seu projeto executa um formatador no commit, use o que ele impõe para não lutar contra o auto-formatador. Quando em dúvida, 2 espaços é o padrão mais seguro.

jsonjavascriptformattingdeveloper-tools

More from Molixa

Try Molixa Tools

50+ free AI tools for content creation, SEO, coding, and more. No signup, no watermark.

Explore all tools