**Título sugerido:**
Como usar `JSON.stringify` sem cair no temido `[object Object]`
Quando você começa a trabalhar com JavaScript e JSON, é questão de tempo até se deparar com um resultado estranho nos logs ou na interface: em vez do conteúdo do objeto, aparece apenas a string `[object Object]`. Isso pode ser frustrante, especialmente quando você está tentando debugar uma função ou exibir dados de forma legível.
Neste artigo, vamos entender por que isso acontece, como o `JSON.stringify` realmente funciona e quais cuidados tomar para evitar armadilhas comuns.
—
## Por que aparece `[object Object]`?
Sempre que você converte um objeto para string de forma implícita em JavaScript, o resultado padrão é:
js
const obj = { nome: ‘Ana’, idade: 30 }
console.log(String(obj)) // “[object Object]”
console.log(obj.toString()) // “[object Object]”
Isso acontece porque, por padrão, objetos em JavaScript herdam de `Object.prototype`, cujo método `toString()` retorna exatamente essa string. Ou seja: quando você faz uma concatenação de string com objeto ou passa um objeto para APIs que esperam string (como `alert`, alguns frameworks de UI, templates simples etc.), o JavaScript chama internamente `toString()` – e o resultado é esse.
A boa notícia é que, para transformar objetos em uma representação de texto realmente útil, usamos `JSON.stringify`.
—
## O que o `JSON.stringify` faz de verdade?
`JSON.stringify` converte um valor JavaScript em uma string no formato JSON. Ele percorre o objeto recursivamente e produz um texto que pode ser transmitido via rede, salvo em arquivos, ou reconstituído depois com `JSON.parse`.
Exemplo básico:
js
const usuario = { nome: ‘Ana’, idade: 30 }
const json = JSON.stringify(usuario)
console.log(json)
// {“nome”:”Ana”,”idade”:30}
Isso é bem diferente de:
js
console.log(usuario.toString())
// “[object Object]”
Resumindo:
– `obj.toString()` → string genérica de objeto (`[object Object]`).
– `JSON.stringify(obj)` → string JSON com o conteúdo serializado.
—
## Onde o `[object Object]` ainda pode surgir mesmo usando JSON?
Mesmo usando `JSON.stringify`, ainda é possível cair em comportamentos inesperados dependendo de como você utiliza o resultado.
Considere:
js
const usuario = { nome: ‘Ana’, idade: 30 }
const json = JSON.stringify(usuario)
// OK:
console.log(json) // {“nome”:”Ana”,”idade”:30}
// Problema: sobrescrevendo o JSON
const dados = { usuario: json }
dados.usuario = { outro: ‘valor’ }
// Em algum lugar depois:
console.log(`Usuário: ${dados.usuario}`)
// Usuário: [object Object]
Por quê?
Porque, na hora de interpolar a string com `dados.usuario`, o JavaScript converte o objeto implicitamente para string, chamando `toString()` – e o resultado é `[object Object]`.
Outro padrão problemático é tentar serializar algo que já não é mais o que você imagina:
js
let dados = { usuario: { nome: ‘Ana’ } }
// Em algum lugar, alguém faz:
dados = String(dados.usuario) // “[object Object]”
// E depois:
const json = JSON.stringify(dados)
console.log(json)
// “\”[object Object]\””
Agora você tem uma string JSON válida, mas com o conteúdo errado. No log, pode até parecer que está tudo bem, porque você vê aspas, mas o valor interno é inútil.
—
## Cuidado com interpolação de strings e templates
Muitos casos de `[object Object]` acontecem simplesmente por causa de interpolação de strings:
js
const usuario = { nome: ‘Ana’, idade: 30 }
console.log(‘Usuário:’, usuario)
// Usuário: { nome: ‘Ana’, idade: 30 } (no Node/browser consoles mais modernos)
console.log(‘Usuário: ‘ + usuario)
// Usuário: [object Object]
console.log(`Usuário: ${usuario}`)
// Usuário: [object Object]
Quando você usa o operador `+` ou template strings com `${}`, o JavaScript converte o objeto para string, e caímos naquele `toString()` padrão.
Se quiser o JSON legível:
js
console.log(`Usuário: ${JSON.stringify(usuario)}`)
// Usuário: {“nome”:”Ana”,”idade”:30}
Ou, se quiser identado:
js
console.log(
`Usuário formatado: ${JSON.stringify(usuario, null, 2)}`
)
Isso vai gerar uma string com quebras de linha e espaçamento, boa para logs.
—
## Usando `JSON.stringify` com formatação (pretty print)
O `JSON.stringify` aceita até três argumentos:
js
JSON.stringify(valor, replacer, space)
– `valor`: o que você quer serializar.
– `replacer` (opcional): função ou array para filtrar/modificar chaves.
– `space` (opcional): número de espaços ou string usada para indentação.
Exemplo com indentação:
js
const usuario = {
nome: ‘Ana’,
idade: 30,
endereco: {
cidade: ‘São Paulo’,
estado: ‘SP’
}
}
const jsonFormatado = JSON.stringify(usuario, null, 2)
console.log(jsonFormatado)
/*
{
“nome”: “Ana”,
“idade”: 30,
“endereco”: {
“cidade”: “São Paulo”,
“estado”: “SP”
}
}
*/
No código:
[imagem: illustration-json-stringify-evitar-object-object-01]
—
## Usando `replacer` para controlar o que vai para o JSON
O parâmetro `replacer` permite controlar o que entra ou como entra na string JSON.
### Replacer como array de chaves
Permite fazer um “filtro branco” de quais propriedades serão incluídas:
js
const usuario = {
nome: ‘Ana’,
idade: 30,
senha: ‘segredo123’
}
const jsonSeguro = JSON.stringify(usuario, [‘nome’, ‘idade’])
console.log(jsonSeguro)
// {“nome”:”Ana”,”idade”:30}
### Replacer como função
Permite transformar valores:
js
const usuario = {
nome: ‘Ana’,
idade: 30,
senha: ‘segredo123’
}
const jsonTransformado = JSON.stringify(usuario, (chave, valor) => {
if (chave === ‘senha’) {
return undefined // remove do JSON
}
return valor
})
console.log(jsonTransformado)
// {“nome”:”Ana”,”idade”:30}
No fluxo de um sistema real, isso evita expor dados sensíveis quando você loga objetos ou monta payloads para APIs.
[imagem: illustration-json-stringify-evitar-object-object-02]
—
## Por que às vezes o `JSON.stringify` retorna `undefined`?
Um erro comum é esperar sempre uma string de volta, mas em alguns casos o retorno é `undefined`:
1. Quando você passa `undefined` diretamente:
js
JSON.stringify(undefined) // undefined
2. Quando você passa funções, `Symbol` ou propriedades com valores `undefined`:
js
JSON.stringify({ a: undefined, b: 1 })
// {“b”:1}
3. Quando o objeto tem referência circular:
js
const obj = {}
obj.self = obj
JSON.stringify(obj)
// TypeError: Converting circular structure to JSON
Esse último caso é comum em estruturas complexas (por exemplo, nós de árvore que referenciam o pai). É importante detectar e tratar isso antes de tentar serializar.
—
## Boas práticas para evitar `[object Object]` e problemas com JSON
Alguns hábitos simples evitam muita dor de cabeça:
1. **Sempre use `JSON.stringify` para objetos em logs textuais**
– Especialmente em templates de log, arquivos, integrações e mensagens para front-end.
2. **Evite concatenar objetos com strings**
– Prefira:
js
console.log(‘Usuário:’, usuario)
// ou:
console.log(`Usuário: ${JSON.stringify(usuario)}`)
3. **Padronize o uso de formatação em logs de debug**
– Crie um helper, por exemplo:
js
const toJson = (obj) => JSON.stringify(obj, null, 2)
console.log(‘Payload da requisição:\n’, toJson(payload))
4. **Cuidado com referência circular**
– Para estruturas complexas, considere:
– Remover referências circulares antes de serializar.
– Ou usar libs que lidam com isso (como `flatted`, `circular-json` e similares).
5. **Não confie cegamente em `JSON.stringify` para anonimização**
– Antes de logar dados de usuário, use `replacer` ou sanitize o objeto para remover:
– Senhas
– Tokens
– Dados pessoais sensíveis (e-mails, CPF, etc.)
—
## Conclusão
O `[object Object]` não é um bug do JavaScript, é apenas o comportamento padrão de conversão de objetos para string. Ele aparece quando deixamos o runtime decidir como representar o objeto em texto.
Para ter controle sobre essa conversão:
– Use `JSON.stringify` sempre que quiser uma representação textual útil de objetos.
– Tenha atenção à interpolação de strings e à concatenação com objetos.
– Explore os parâmetros `replacer` e `space` para filtrar dados e formatar a saída.
Com esses cuidados, seus logs, respostas de API e mensagens de debug ficam mais claros, seguros e muito mais fáceis de entender.