JSON Formatter JavaScript — JSON.stringify()

·Front-end & Node.js Developer·Revisado porMarcus Webb·Publicado

Use o Formatador e Embelezador JSON gratuito diretamente no seu navegador — sem instalação.

Experimentar Formatador e Embelezador JSON online →

Quando depuro respostas de API no Node.js, uma parede de JSON minificado é a primeira coisa que me atrasa — uma chamada a JSON.stringify(data, null, 2) e a estrutura se torna instantaneamente legível. Para formatar JSON em JavaScript, você não precisa de nada além do próprio runtime: JSON.stringify está integrado em todos os navegadores e no Node.js, sem instalação alguma. Se você só precisa de um resultado rápido sem escrever código, o Formatador JSON do ToolDeck faz isso instantaneamente. Este guia cobre tudo que é prático: o parâmetro space, arrays e funções replacer, o tratamento de Date, BigInte referências circulares, leitura e escrita de arquivos JSON no Node.js (18+), formatação pela linha de comando, e a biblioteca fast-json-stringify para serialização em produção.

  • JSON.stringify(data, null, 2) está integrado em todos os navegadores e Node.js — sem instalação.
  • O parâmetro replacer aceita um array (lista de chaves) ou uma função (transformar valores) — use-o para mascarar campos sensíveis.
  • Objetos Date são serializados automaticamente via toJSON() → string ISO 8601; BigInt lança TypeError e requer um replacer personalizado.
  • Referências circulares lançam TypeError — corrija com um Set seen em uma função replacer, ou use a biblioteca flatted.
  • Para formatação pela CLI use node -p "JSON.stringify(require('./file.json'),null,2)" — sem ferramentas adicionais.

O que é formatação JSON?

A formatação JSON (também chamada de pretty-printing) transforma uma string JSON compacta e minificada em uma apresentação legível com indentação consistente e quebras de linha. Os dados subjacentes são idênticos — apenas o espaço em branco muda. O JSON compacto é ideal para transferência pela rede, onde cada byte importa; o JSON formatado é ideal para depuração, revisão de código e inspeção de logs. A função JSON.stringify() do JavaScript lida com ambos em uma única chamada ao alternar o parâmetro space.

Before · json
After · json
{"orderId":"ord_8f2a91bc","status":"shipped","items":[{"sku":"HDMI-4K-2M","qty":2,"unitPrice":12.99}],"total":25.98}
{
  "orderId": "ord_8f2a91bc",
  "status": "shipped",
  "items": [
    {
      "sku": "HDMI-4K-2M",
      "qty": 2,
      "unitPrice": 12.99
    }
  ],
  "total": 25.98
}

JSON.stringify() — O formatador integrado

JSON.stringify() é uma função global em todos os ambientes JavaScript — navegadores, Node.js, Deno, Bun — sem necessidade de importação. Seu terceiro argumento, space, controla a indentação: passe um número para essa quantidade de espaços por nível, ou a string '\t' para tabulações. Omitir (ou passar null) produz saída compacta em uma única linha.

JavaScript — exemplo mínimo funcional
const serverConfig = {
  host: "api.payments.internal",
  port: 8443,
  workers: 4,
  tls: { enabled: true, cert: "/etc/ssl/certs/api.pem" },
  rateLimit: { requestsPerMinute: 1000, burst: 50 }
}

console.log(JSON.stringify(serverConfig, null, 2))
// {
//   "host": "api.payments.internal",
//   "port": 8443,
//   "workers": 4,
//   "tls": {
//     "enabled": true,
//     "cert": "/etc/ssl/certs/api.pem"
//   },
//   "rateLimit": {
//     "requestsPerMinute": 1000,
//     "burst": 50
//   }
// }

O parâmetro space aceita um número (1–10 espaços) ou uma string. Passar um caractere de tabulação produz uma saída que muitos editores e ferramentas de diff preferem. Você também pode combinar os três parâmetros — aqui está um padrão real que uso ao escrever JSON formatado em arquivos de configuração:

JavaScript — variações de space
const telemetryEvent = {
  eventId: "evt_3c7f9a2b",
  service: "checkout-api",
  severity: "warn",
  latencyMs: 342,
  region: "eu-west-1",
  tags: ["payment", "timeout", "retry"]
}

// Indentação de 2 espaços (mais comum em projetos JS)
JSON.stringify(telemetryEvent, null, 2)

// Indentação com tabulação (preferida por alguns linters e ferramentas de config)
JSON.stringify(telemetryEvent, null, '\t')

// Compacto — sem espaços em branco (para transferência pela rede)
JSON.stringify(telemetryEvent)
// {"eventId":"evt_3c7f9a2b","service":"checkout-api",...}
Nota:Valores undefined, funções e valores Symbol são silenciosamente omitidos da saída. Se o valor de uma propriedade for undefined, essa chave não aparecerá na string serializada — é uma fonte comum de bugs ao registrar objetos com campos opcionais.

Funções replacer — Filtrar e transformar a saída

O segundo argumento de JSON.stringify() é o replacer. Ele tem duas formas: um array que permite apenas as chaves especificadas, ou uma função que é chamada para cada par chave/valor e pode filtrar, transformar ou redigir valores. Uso o array quando preciso de um subconjunto rápido, e a função quando preciso mascarar dados sensíveis antes de registrá-los.

Replacer de array — Lista de chaves específicas

JavaScript — replacer de array
const order = {
  orderId: "ord_8f2a91bc",
  customer: {
    id: "usr_4421",
    email: "j.silva@exemplo.com.br",
    passwordHash: "bcrypt:$2b$12$XKzV..."
  },
  items: [{ sku: "HDMI-4K-2M", qty: 2, unitPrice: 12.99 }],
  createdAt: "2026-03-10T14:22:00Z"
}

// Incluir apenas campos seguros no registro
const safeLog = JSON.stringify(order, ["orderId", "items", "createdAt"], 2)
// {
//   "orderId": "ord_8f2a91bc",
//   "items": [{ "sku": "HDMI-4K-2M", "qty": 2, "unitPrice": 12.99 }],
//   "createdAt": "2026-03-10T14:22:00Z"
// }
// passwordHash e customer.email ficam excluídos

Replacer de função — Transformar valores

JavaScript — replacer de função
const auditRecord = {
  requestId: "req_7d2e91",
  user: { id: "usr_4421", email: "j.silva@exemplo.com.br", apiKey: "sk-live-eKx9..." },
  action: "update_billing",
  timestamp: new Date("2026-03-10T14:22:00Z"),
  durationMs: 87
}

function safeReplacer(key, value) {
  // Redigir campos que parecem segredos ou PII
  if (key === "apiKey") return "[REDIGIDO]"
  if (key === "email") return value.replace(/(?<=.{2}).+(?=@)/, "***")
  return value
}

console.log(JSON.stringify(auditRecord, safeReplacer, 2))
// {
//   "requestId": "req_7d2e91",
//   "user": { "id": "usr_4421", "email": "j.***@exemplo.com.br", "apiKey": "[REDIGIDO]" },
//   "action": "update_billing",
//   "timestamp": "2026-03-10T14:22:00.000Z",
//   "durationMs": 87
// }
Nota:A função replacer é chamada com this definido como o objeto que contém a chave atual. A primeira chamada passa uma string vazia como chave e o valor completo sendo serializado como valor — retorne-o sem alterações para prosseguir com a serialização normal.

Tratando tipos não serializáveis

Nem todos os valores JavaScript se mapeiam perfeitamente para JSON. Conhecer o comportamento de cada tipo evita perda silenciosa de dados e erros inesperados em código de produção.

Date — Automático via toJSON()

Objetos Date implementam um método toJSON() que retorna uma string ISO 8601. JSON.stringify() chama toJSON() automaticamente antes de serializar, portanto nenhum tratamento personalizado é necessário.

JavaScript — serialização de Date
const webhook = {
  eventType: "payment.succeeded",
  occurredAt: new Date("2026-03-10T14:22:00Z"),
  processedAt: new Date()
}

JSON.stringify(webhook, null, 2)
// {
//   "eventType": "payment.succeeded",
//   "occurredAt": "2026-03-10T14:22:00.000Z",
//   "processedAt": "2026-03-10T14:22:01.347Z"
// }

// Qualquer objeto com um método toJSON() recebe o mesmo tratamento:
const custom = { toJSON: () => "valor-personalizado", hidden: 42 }
JSON.stringify(custom) // '"valor-personalizado"'

Classes personalizadas — Implementar toJSON()

Qualquer classe pode implementar um método toJSON() e JSON.stringify() o chamará automaticamente durante a serialização. Isso é mais limpo do que um replacer global para tipos de domínio que aparecem em todo o código.

JavaScript — toJSON() personalizado
class Money {
  constructor(amount, currency) {
    this.amount = amount
    this.currency = currency
  }
  toJSON() {
    // Chamado automaticamente por JSON.stringify
    return { amount: this.amount, currency: this.currency, formatted: `${this.currency} ${this.amount.toFixed(2)}` }
  }
}

class OrderId {
  constructor(id) { this.id = id }
  toJSON() { return this.id }  // Serializar como string simples
}

const invoice = {
  invoiceId: new OrderId('inv_8f2a91bc'),
  subtotal: new Money(199.00, 'BRL'),
  tax:      new Money(15.92, 'BRL'),
  issuedAt: new Date('2026-03-10T14:22:00Z')
}

JSON.stringify(invoice, null, 2)
// {
//   "invoiceId": "inv_8f2a91bc",
//   "subtotal": { "amount": 199, "currency": "BRL", "formatted": "BRL 199.00" },
//   "tax": { "amount": 15.92, "currency": "BRL", "formatted": "BRL 15.92" },
//   "issuedAt": "2026-03-10T14:22:00.000Z"
// }
Nota:toJSON() tem prioridade sobre a função replacer. Se ambos estiverem presentes, toJSON() é executado primeiro — o replacer recebe o valor já convertido, não a instância de classe original.

BigInt — TypeError sem um replacer

JavaScript — replacer para BigInt
// Isso lança: TypeError: Do not know how to serialize a BigInt
// JSON.stringify({ sessionId: 9007199254741234n })

// Solução: converter BigInt para string no replacer
function bigIntReplacer(_key, value) {
  return typeof value === 'bigint' ? value.toString() : value
}

const metrics = {
  requestCount: 9007199254741234n,  // excede Number.MAX_SAFE_INTEGER
  service: "ingestion-worker",
  region: "us-east-1"
}

JSON.stringify(metrics, bigIntReplacer, 2)
// {
//   "requestCount": "9007199254741234",
//   "service": "ingestion-worker",
//   "region": "us-east-1"
// }

Referências circulares — TypeError sem um Set seen

JavaScript — replacer para referências circulares
// Isso lança: TypeError: Converting circular structure to JSON
// const node = { id: "n1" }; node.self = node; JSON.stringify(node)

// Solução: rastrear objetos vistos com um WeakSet
function circularReplacer() {
  const seen = new WeakSet()
  return function (_key, value) {
    if (typeof value === 'object' && value !== null) {
      if (seen.has(value)) return '[Circular]'
      seen.add(value)
    }
    return value
  }
}

const parent = { id: "node_parent", label: "root" }
const child  = { id: "node_child", parent }
parent.child = child  // circular

JSON.stringify(parent, circularReplacer(), 2)
// {
//   "id": "node_parent",
//   "label": "root",
//   "child": { "id": "node_child", "parent": "[Circular]" }
// }

// Alternativa: npm install flatted
// import { stringify } from 'flatted'
// stringify(parent)  // trata refs circulares nativamente

Referência de parâmetros de JSON.stringify()

Os três parâmetros são bem suportados em todos os runtimes JavaScript modernos. Os valores padrão produzem JSON compacto em uma única linha — passe os parâmetros explicitamente para obter saída legível.

Parâmetro
Tipo
Padrão
Descrição
value
any
O valor a serializar. Objetos, arrays, strings, números, booleanos e null são suportados nativamente.
replacer
function | Array<string | number> | null
null
Filtra ou transforma pares chave/valor. Array = lista de chaves a incluir. Função = chamada para cada chave/valor.
space
number | string | null
null
Indentação. Número = espaços por nível (máx. 10). String = indentação literal (ex.: "\t"). null ou 0 = saída compacta.

Formatar JSON de um arquivo e resposta de API

No Node.js (18+) você frequentemente precisa reformatar um arquivo de configuração JSON ou exibir com formatação uma resposta de API para depuração. Ambos os padrões usam a mesma abordagem em dois passos: analisar o texto bruto com JSON.parse() e depois resserializar com JSON.stringify().

Lendo e reescrevendo um arquivo de configuração JSON

Node.js 18+ — reformatar um arquivo JSON (ESM)
import { readFileSync, writeFileSync } from 'fs'

try {
  const raw = readFileSync('./config/database.json', 'utf8')
  const config = JSON.parse(raw)
  writeFileSync('./config/database.json', JSON.stringify(config, null, 2))
  console.log('Config reformatado com sucesso')
} catch (err) {
  console.error('Falha ao reformatar config:', err.message)
  // JSON.parse lança SyntaxError se o arquivo contém JSON inválido
  // readFileSync lança ENOENT se o arquivo não existe
}

Reformatação assíncrona de arquivo (fs/promises)

Node.js 18+ — reformatação assíncrona de arquivo
import { readFile, writeFile } from 'fs/promises'

async function reformatJson(filePath) {
  const raw = await readFile(filePath, 'utf8')
  const parsed = JSON.parse(raw)
  const formatted = JSON.stringify(parsed, null, 2)
  await writeFile(filePath, formatted, 'utf8')
  return { keys: Object.keys(parsed).length }
}

// Uso
const { keys } = await reformatJson('./config/feature-flags.json')
console.log(`Reformatadas ${keys} chaves de nível superior`)

Exibir com formato JSON de uma resposta fetch()

Ao construir ou depurar um cliente de API no Node.js 18+ ou no navegador, formatar o corpo da resposta é a maneira mais rápida de entender o que o servidor retornou. O padrão padrão é response.json() (objeto analisado) passado para JSON.stringify(). Se você precisar da string bruta primeiro — por exemplo, para calcular um hash ou registrá-la literalmente — use response.text() e depois JSON.parse().

JavaScript — fetch + formatação (Node.js 18+ ou navegador)
// Padrão 1: response.json() → exibir com formato
async function debugEndpoint(url) {
  const res = await fetch(url, {
    headers: { Authorization: `Bearer ${process.env.API_TOKEN}` }
  })
  if (!res.ok) throw new Error(`HTTP ${res.status}: ${res.statusText}`)

  const data = await res.json()
  console.log(JSON.stringify(data, null, 2))
}

await debugEndpoint('https://api.stripe.com/v1/charges?limit=3')
JavaScript — response.text() quando você precisa da string bruta primeiro
// Padrão 2: response.text() → analisar → formatar
// Útil quando você quer registrar a resposta bruta E exibi-la com formato
async function inspectRawResponse(url) {
  const res = await fetch(url)
  const raw = await res.text()

  console.log('Comprimento da resposta bruta:', raw.length)
  try {
    const parsed = JSON.parse(raw)
    console.log('Formatado:')
    console.log(JSON.stringify(parsed, null, 2))
  } catch {
    console.error('A resposta não é JSON válido:', raw.slice(0, 200))
  }
}

Formatação pela linha de comando

O Node.js tem capacidade suficiente para formatar JSON no terminal sem ferramentas adicionais. Esses one-liners são úteis em scripts de CI, pipelines de implantação e aliases de shell. Para uso interativo ainda mais rápido, instale jq — o padrão de facto para manipulação de JSON na linha de comando.

bash — formatar um arquivo JSON com Node.js
# Formatar package.json usando node -p (print)
node -p "JSON.stringify(require('./package.json'), null, 2)"

# Formatar do stdin (compatível com pipe, funciona em CI)
echo '{"port":3000,"env":"production"}' | node -e "
  const d = require('fs').readFileSync(0, 'utf8')
  console.log(JSON.stringify(JSON.parse(d), null, 2))
"

# Formatar uma resposta de API salva em arquivo
cat api-response.json | node -e "
  process.stdin.setEncoding('utf8')
  let s = ''
  process.stdin.on('data', c => s += c)
  process.stdin.on('end', () => console.log(JSON.stringify(JSON.parse(s), null, 2)))
"
bash — alternativas universais
# Alternativa com Python (pré-instalado no macOS e na maioria do Linux)
cat api-response.json | python3 -m json.tool

# jq — mais rápido e com mais recursos (brew install jq / apt install jq)
cat api-response.json | jq .

# jq — formatar e filtrar em um único passo
cat api-response.json | jq '.data.users[] | {id, email}'
Nota:Ao executar o Node.js em modo ESM (ex.: com "type": "module" no package.json), require() não está disponível em one-liners. Use --input-type=module e fs.readFileSync em vez disso, ou mude para node -e com um trecho CommonJS como mostrado acima.

Se você não está no terminal — colando uma resposta do Postman ou um arquivo de logs — o Formatador JSON do ToolDeck permite colar, formatar e copiar em uma etapa com destaque de sintaxe e validação integrada.

Alternativa de alto desempenho — fast-json-stringify

fast-json-stringify gera uma função serializadora dedicada a partir de um JSON Schema. Como conhece a forma dos dados antecipadamente, pode pular a verificação de tipos e usar concatenação de strings em vez de descida recursiva — benchmarks tipicamente mostram melhoria de throughput de 2–5× em relação a JSON.stringify() em payloads grandes e repetitivos. Eu o uso em rotas de API de alta frequência onde o custo de serialização aparece nos traces do profiler.

bash
npm install fast-json-stringify
JavaScript — fast-json-stringify para eventos de telemetria
import fastJson from 'fast-json-stringify'

const serializeTelemetryEvent = fastJson({
  title: 'TelemetryEvent',
  type: 'object',
  properties: {
    eventId:   { type: 'string' },
    service:   { type: 'string' },
    severity:  { type: 'string', enum: ['info', 'warn', 'error'] },
    latencyMs: { type: 'integer' },
    timestamp: { type: 'string' },
    region:    { type: 'string' }
  },
  required: ['eventId', 'service', 'severity', 'latencyMs', 'timestamp']
})

const event = {
  eventId:   'evt_3c7f9a2b',
  service:   'checkout-api',
  severity:  'warn',
  latencyMs: 342,
  timestamp: new Date().toISOString(),
  region:    'eu-west-1'
}

const json = serializeTelemetryEvent(event)
// '{"eventId":"evt_3c7f9a2b","service":"checkout-api","severity":"warn",...}'
Nota:fast-json-stringify é projetado para serialização em produção de dados estruturados — sempre produz saída compacta (sem pretty-printing). Para saída legível durante o desenvolvimento, use JSON.stringify(data, null, 2) normalmente.

Saída no terminal com realce de sintaxe

A função integrada do Node.js util.inspect() produz saída colorida e legível, otimizada para exibição no terminal. Trata referências circulares e BigInt nativamente, e renderiza recursivamente objetos aninhados em qualquer profundidade. A saída não é JSON válido — usa sintaxe JavaScript (ex.: true em vez de true, mas renderiza funções e Symbols em vez de omiti-los), o que a torna ideal para scripts de depuração no Node.js, mas inadequada para respostas de API ou saída em arquivo.

Node.js 18+ — util.inspect com cores
import { inspect } from 'util'

const payload = {
  requestId: "req_7d2e91",
  user: { id: "usr_4421", roles: ["admin", "billing"] },
  metadata: { ipAddress: "203.0.113.42", userAgent: "Mozilla/5.0" },
  createdAt: new Date()
}

// depth: null → expandir todos os níveis aninhados; colors: true → cores ANSI no terminal
console.log(inspect(payload, { colors: true, depth: null }))
Aviso:Não use util.inspect() para JSON escrito em arquivos, enviado pela rede ou armazenado em banco de dados. Sua saída não é JSON válido e causará erros de análise em qualquer sistema downstream que chame JSON.parse() sobre ela. Reserve-a exclusivamente para depuração interativa no terminal.

Trabalhando com arquivos JSON grandes

JSON.parse() carrega o arquivo inteiro na memória antes de analisar — adequado para payloads pequenos, mas impraticável para arquivos acima de 50–100 MB, como exportações de banco de dados, dumps de logs de aplicação ou lotes de análise. Para esses casos, os Streams do Node.js e a biblioteca stream-json permitem processar registros um por vez sem sobrecarregar o heap.

Análise em streaming com stream-json

bash
npm install stream-json
Node.js 18+ — stream-json para arrays grandes
import { pipeline } from 'stream/promises'
import { createReadStream } from 'fs'
import { parser } from 'stream-json'
import { streamArray } from 'stream-json/streamers/StreamArray.js'

// events.json = array de milhões de objetos — nunca carregado completamente na memória
await pipeline(
  createReadStream('./events.json'),
  parser(),
  streamArray(),
  async function* (source) {
    for await (const { value: event } of source) {
      if (event.severity === 'error') {
        console.log(JSON.stringify(event, null, 2))
      }
    }
  }
)

NDJSON / JSON Lines — Sem dependências extras

NDJSON (Newline Delimited JSON) armazena um objeto JSON por linha e é comum em exportações do Kafka, saídas do BigQuery e pipelines de logs estruturados. O módulo integrado readline do Node.js trata isso sem nenhum pacote de terceiros.

Node.js 18+ — NDJSON com readline
import { createReadStream } from 'fs'
import { createInterface } from 'readline'

// Formato: um objeto JSON por linha (logs, exportações do Kafka, BigQuery)
const rl = createInterface({
  input: createReadStream('./logs.ndjson'),
  crlfDelay: Infinity
})

for await (const line of rl) {
  if (!line.trim()) continue
  const entry = JSON.parse(line)
  if (entry.level === 'error') {
    console.log(JSON.stringify(entry, null, 2))
  }
}
Nota:Mude de JSON.parse() para streaming quando seu arquivo JSON exceder 50–100 MB ou ao processar um stream ilimitado (Kafka, pipeline de logs). Para NDJSON / JSON Lines, use readline — não requer dependências extras.

Erros comuns

Esses quatro erros aparecem repetidamente em revisões de código e relatórios de bugs em produção. Cada um envolve um comportamento sutil de JSON.stringify() que é fácil de perder e difícil de depurar depois.

Esquecer que valores undefined são silenciosamente omitidos

Problema: Propriedades de objeto com valores undefined são omitidas completamente da saída JSON — sem aviso ou erro. Isso causa perda invisível de dados quando campos opcionais existem no objeto.

Solução: Use null para valores intencionalmente ausentes que precisam aparecer na saída serializada. Reserve undefined apenas para campos que devem ser excluídos do JSON.

Before · JavaScript
After · JavaScript
const userProfile = {
  userId: "usr_4421",
  displayName: "João Silva",
  avatarUrl: undefined,   // vai desaparecer silenciosamente
  bio: undefined          // vai desaparecer silenciosamente
}

JSON.stringify(userProfile, null, 2)
// { "userId": "usr_4421", "displayName": "João Silva" }
// avatarUrl e bio sumiram — sem aviso
const userProfile = {
  userId: "usr_4421",
  displayName: "João Silva",
  avatarUrl: null,   // explicitamente ausente — aparece na saída
  bio: null          // explicitamente ausente — aparece na saída
}

JSON.stringify(userProfile, null, 2)
// {
//   "userId": "usr_4421",
//   "displayName": "João Silva",
//   "avatarUrl": null,
//   "bio": null
// }
BigInt lança TypeError

Problema: Passar um valor BigInt para JSON.stringify() lança um TypeError em tempo de execução. É uma falha total, não omissão silenciosa — vai aparecer em produção se algum campo numérico exceder Number.MAX_SAFE_INTEGER.

Solução: Use uma função replacer que converta valores BigInt para strings antes da serialização. Alternativamente, converta BigInt para string ou Number na camada de dados antes de passar para JSON.stringify.

Before · JavaScript
After · JavaScript
const session = {
  sessionId: 9007199254741234n,  // literal BigInt
  userId: "usr_4421",
  startedAt: "2026-03-10T14:00:00Z"
}

JSON.stringify(session, null, 2)
// Uncaught TypeError: Do not know how to serialize a BigInt
function bigIntReplacer(_key, value) {
  return typeof value === 'bigint' ? value.toString() : value
}

const session = {
  sessionId: 9007199254741234n,
  userId: "usr_4421",
  startedAt: "2026-03-10T14:00:00Z"
}

JSON.stringify(session, bigIntReplacer, 2)
// {
//   "sessionId": "9007199254741234",
//   "userId": "usr_4421",
//   "startedAt": "2026-03-10T14:00:00Z"
// }
Referências circulares causam falha

Problema: Objetos que referenciam a si mesmos — comuns em árvores DOM, listas encadeadas e alguns conjuntos de resultados de ORM — lançam um TypeError quando passados para JSON.stringify(). O erro ocorre apenas no momento da serialização, muitas vezes longe de onde a referência circular foi criada.

Solução: Use uma função replacer com um WeakSet para detectar e substituir referências circulares, ou instale a biblioteca flatted como substituto direto que trata estruturas circulares nativamente.

Before · JavaScript
After · JavaScript
const dept = { id: "dept_eng", name: "Engenharia" }
const team = { id: "team_frontend", dept }
dept.teams = [team]  // circular: dept → team → dept

JSON.stringify(dept, null, 2)
// Uncaught TypeError: Converting circular structure to JSON
import { stringify } from 'flatted'  // npm install flatted

const dept = { id: "dept_eng", name: "Engenharia" }
const team = { id: "team_frontend", dept }
dept.teams = [team]

// flatted trata refs circulares — nota: saída é formato flatted, não JSON padrão
stringify(dept)

// Ou use um replacer baseado em WeakSet para JSON padrão:
function circularReplacer() {
  const seen = new WeakSet()
  return (_key, value) => {
    if (typeof value === 'object' && value !== null) {
      if (seen.has(value)) return '[Circular]'
      seen.add(value)
    }
    return value
  }
}
JSON.stringify(dept, circularReplacer(), 2)
Usar space > 10 (limitado silenciosamente)

Problema: Passar um valor de space maior que 10 para JSON.stringify() não lança um erro — o valor é silenciosamente limitado a 10. Desenvolvedores que esperam 20 espaços por nível de indentação para estruturas profundas obterão apenas 10, gerando formatação inesperada nos arquivos gerados.

Solução: A indentação máxima é 10 espaços. Para estruturas profundas, prefira indentação de 2 espaços (a convenção mais comum em projetos JavaScript) e use editores com colapso para navegação.

Before · JavaScript
After · JavaScript
const deepConfig = { server: { tls: { certs: { primary: "/etc/ssl/api.pem" } } } }

// Esperando indentação de 20 espaços — mas space é limitado a 10
JSON.stringify(deepConfig, null, 20)
// Mesma saída que JSON.stringify(deepConfig, null, 10)
// Sem erro, sem aviso — truncado silenciosamente
const deepConfig = { server: { tls: { certs: { primary: "/etc/ssl/api.pem" } } } }

// Use 2 (maioria dos projetos) ou 4 espaços — nunca ultrapasse 10
JSON.stringify(deepConfig, null, 2)
// {
//   "server": {
//     "tls": {
//       "certs": {
//         "primary": "/etc/ssl/api.pem"
//       }
//     }
//   }
// }

JSON.stringify vs alternativas — Comparação rápida

Situações diferentes exigem ferramentas diferentes. JSON.stringify com um replacer cobre a maioria dos casos de uso em produção sem dependências. util.inspect é a escolha certa para depuração rápida no terminal quando você precisa de saída colorida e não precisa de JSON válido. fast-json-stringify vale a pena em rotas de alto throughput onde o profiling mostra custo de serialização; para todo o resto, a sobrecarga de manutenção do esquema não compensa.

Método
Saída formatada
JSON válido
Não-ASCII
Tipos personalizados
Refs. circulares
Requer instalação
JSON.stringify
⚠️ via replacer
✗ (lança erro)
Não
JSON.stringify + replacer
✅ controle total
Não
util.inspect
✅ nativo
Não (Node integrado)
fast-json-stringify
❌ apenas esquema
npm install
flatted
✗ (formato próprio)
✅ apenas circulares
npm install
jq (CLI)
N/A
N/A
Instalação do sistema

Perguntas frequentes

Como formato JSON com indentação em JavaScript?

Chame JSON.stringify(data, null, 2) — o terceiro argumento controla a indentação. Passe 2 ou 4 para espaços, ou "\t" para tabulações. Nenhuma importação ou instalação é necessária: JSON é um objeto global em todos os ambientes JavaScript, incluindo navegadores e Node.js.

JavaScript
const config = { host: "api.payments.internal", port: 8443, tls: true }
console.log(JSON.stringify(config, null, 2))
// {
//   "host": "api.payments.internal",
//   "port": 8443,
//   "tls": true
// }

O que faz o parâmetro `space` em JSON.stringify()?

O parâmetro space controla a indentação na saída. Passe um número (1–10) para essa quantidade de espaços por nível, ou uma string como "\t" para usar um caractere de tabulação. Valores acima de 10 são silenciosamente limitados a 10. Passar null, 0 ou omitir o parâmetro produz JSON compacto em uma única linha.

JavaScript
const data = { service: "payments", version: 3, active: true }

JSON.stringify(data, null, 2)   // indentação de 2 espaços
JSON.stringify(data, null, 4)   // indentação de 4 espaços
JSON.stringify(data, null, '\t') // indentação com tabulação
JSON.stringify(data)            // compacto: {"service":"payments","version":3,"active":true}

Por que JSON.stringify() retorna undefined para alguns valores?

JSON.stringify omite silenciosamente as propriedades de objetos cujos valores são undefined, funções ou Symbols — esses tipos não têm representação em JSON. Se o valor de nível superior for undefined, a função retorna undefined (não a string "undefined"). Use null em vez de undefined para campos opcionais que precisam aparecer na saída.

JavaScript
const event = {
  traceId: "tr_9a2f",
  handler: () => {},        // função — omitida
  requestId: undefined,     // undefined — omitido
  sessionId: Symbol("s"),   // Symbol — omitido
  status: "ok"
}
JSON.stringify(event, null, 2)
// { "traceId": "tr_9a2f", "status": "ok" }

Como lidar com objetos Date ao formatar JSON?

Objetos Date possuem um método toJSON() integrado que retorna uma string ISO 8601, então JSON.stringify os trata automaticamente. Você não precisa de um replacer personalizado para datas — o valor serializado será uma string como "2026-03-10T14:22:00.000Z".

JavaScript
const order = {
  orderId: "ord_8f2a91bc",
  placedAt: new Date("2026-03-10T14:22:00Z"),
  total: 42.98
}
JSON.stringify(order, null, 2)
// {
//   "orderId": "ord_8f2a91bc",
//   "placedAt": "2026-03-10T14:22:00.000Z",
//   "total": 42.98
// }

Como formato uma string JSON (não um objeto) em JavaScript?

Analise a string com JSON.parse() primeiro e, em seguida, resserialize-a com JSON.stringify(). As duas chamadas podem ser encadeadas em uma única linha para depuração rápida.

JavaScript
const raw = '{"endpoint":"/api/v2/users","timeout":30,"retry":true}'
const formatted = JSON.stringify(JSON.parse(raw), null, 2)
console.log(formatted)
// {
//   "endpoint": "/api/v2/users",
//   "timeout": 30,
//   "retry": true
// }

Posso usar JSON.stringify() no navegador?

Sim. JSON é um objeto global integrado em todos os navegadores modernos desde o IE8 — sem necessidade de tags de script ou importações. Abra o console do DevTools e chame JSON.stringify() diretamente. Funciona de forma idêntica à versão do Node.js, com a mesma assinatura de parâmetros e as mesmas limitações em relação a BigInt e referências circulares.

JavaScript
// Funciona no Chrome, Firefox, Safari, Edge — sem importações
const payload = { userId: "usr_7b3c", action: "checkout", cart: ["SKU-001", "SKU-002"] }
copy(JSON.stringify(payload, null, 2)) // copy() é um helper do DevTools

O JavaScript oferece controle total — funções replacer, toJSON() personalizado, processamento de arquivos grandes no Node.js. Quando você só precisa inspecionar ou compartilhar um trecho formatado, o Formatador JSON do ToolDeck é o caminho mais rápido: cole seu JSON e obtenha um resultado formatado e destacado sem nenhuma configuração de ambiente.

Ferramentas relacionadas

Também disponível em:PythonGoBash
AC
Alex ChenFront-end & Node.js Developer

Alex is a front-end and Node.js developer with extensive experience building web applications and developer tooling. He is passionate about web standards, browser APIs, and the JavaScript ecosystem. In his spare time he contributes to open-source projects and writes about modern JavaScript patterns, performance optimisation, and everything related to the web platform.

MW
Marcus WebbRevisor técnico

Marcus specialises in JavaScript performance, build tooling, and the inner workings of the V8 engine. He has spent years profiling and optimising React applications, working on bundler configurations, and squeezing every millisecond out of critical rendering paths. He writes about Core Web Vitals, JavaScript memory management, and the tools developers reach for when performance really matters.