O que é express.json()?
O express.json() é uma função de middleware integrada do Express.js (disponível a partir da versão 4.16.0), cuja função principal é analisar os dados no corpo de requisições HTTP no formato JSON, convertendo-os em objetos JavaScript e anexando-os à propriedade req.body para uso posterior por rotas e outros middlewares.
Em termos simples: quando um cliente envia dados no formato JSON para o servidor (por exemplo, em requisições POST/PUT), sem o uso do express.json(), o req.body do seria undefined. Com ele, você pode acessar diretamente os dados JSON analizados através de req.body.
Informação adicional: Antes do Express 4.16.0, a análise de corpos de requisição JSON dependia de middlewares de terceiros (como body-parser). Posteriormente, o Express incorporou as funcionalidades principais do body-parser, e o express.json() essencialmente é uma versão embutida do body-parser.json().
Por que precisamos do express.json()?
O corpo de uma requisição HTTP é, em sua essência, um "fluxo de dados binários". Mesmo quando o cliente envia uma string JSON (como {"username":"joao","idade":30}), os dados brutos recebidos pelo servidor são uma sequência de caracteres não estruturados, não um objeto JavaScript diretamente utilizável.
Sem o express.json() para fazer a análise:
- Você precisaria monitorar manualmente os eventos
dataeenddo objetoreqpara concatenar o fluxo de dados brutos; - Manualmente converter a string concatenada em um objeto JS (
JSON.parse()); - Lidar com codificação, exceções (como formato JSON inválido) e outros problemas, o que é extremamente trabalhoso.
O express.json() encapsula essa série de operações, permitindo que acessemos dados estruturados diretamente através de req.body, aumentando a eficiência do desenvolvimento.
Uso Básico: Como utilizar o express.json()?
1. Uso Global (Recomendado - analisa todas as requisições qualificadas)
Registre-o na instância Express usando app.use(), afetando todas as rotas subsqeuentes:
// 1. Importar Express
const servidorExpress = require('express');
// 2. Criar instância Express
const app = servidorExpress();
// 3. Registrar middleware express.json() (efeito global)
app.use(express.json());
// 4. Definir rota, usando req.body para obter dados JSON analisados
app.post('/api/usuario', (req, res) => {
// Agora req.body foi analisado em um objeto JS
console.log('Dados JSON analisados:', req.body);
console.log('Nome de usuário:', req.body.nome);
console.log('Idade:', req.body.idade);
res.status(200).json({
codigo: 200,
mensagem: 'Requisição bem-sucedida',
dados: req.body
});
});
// 5. Iniciar servidor
const porta = 3000;
app.listen(porta, () => {
console.log(`Servidor rodando em http://localhost:${porta}`);
});
2. Uso Local (apenas para rotas específicas)
Se você precisar analisar apenas algumas rotas de corpos de requisição JSON, pode registrar separadamente na definição da rota:
const servidorExpress = require('express');
const app = servidorExpress();
// Apenas para a rota POST /api/pedido
app.post('/api/pedido', express.json(), (req, res) => {
console.log('Dados do pedido:', req.body);
res.json({ codigo: 200, dados: req.body });
});
// Outras rotas não analisam corpo JSON (req.body será undefined)
app.post('/api/teste', (req, res) => {
console.log('req.body não analisado:', req.body); // undefined
res.send('Rota de teste');
});
app.listen(3000, () => console.log('Servidor iniciado'));
3. Teste e Validação
Você pode usar Postman, curl ou Axios para enviar requisições JSON de teste:
(1) Teste com comando curl
curl -X POST \
http://localhost:3000/api/usuario \
-H 'Content-Type: application/json' \
-d '{
"nome": "joao",
"idade": 30,
"genero": "masculino"
}'
(2) Teste com frontend Axios
axios.post('http://localhost:3000/api/usuario', {
nome: 'joao',
idade: 30,
genero: 'masculino'
}, {
headers: {
'Content-Type': 'application/json' // O frontend precisa especificar este cabeçalho (já incluído por padrão)
}
}).then(res => console.log(res.data));
(3) Resultado da Resposta
O console do servidor exibirá:
Dados JSON analisados: { nome: 'joao', idade: 30, genero: 'masculino' }
Nome de usuário: joao
Idade: 30
O cliente receberá a resposta:
{
"codigo": 200,
"mensagem": "Requisição bem-sucedida",
"dados": {
"nome": "joao",
"idade": 30,
"genero": "masculino"
}
}
Configuração Avançada: Parâmetros Opcionais do express.json()
O express.json() aceita um objeto de configuração para personalizar o comportamento de análise, com os seguintes parâmetros comuns:
| Parâmetro | Tipo | Valor Padrão | Descrição |
|---|---|---|---|
inflar |
Booleano | true |
Se deve analisar corpos de requisição em formato "comprimido" (como dados JSON compactados com gzip/deflate); definido como false rejeita corpos de requisição compactados |
limite |
Texto/Número | '100kb' |
Limita o tamanho do corpo da requisição; pode ser número (unidade: bytes) ou string (como '1mb', '2kb'); exceder esse tamanho gera erro 413 (Payload Too Large) |
reviver |
Função | null |
Segundo parâmetro passado para JSON.parse(), usado para personalizar o processo de análise (como converter strings de data em objetos Date) |
estrito |
Booleano | true |
Se deve ativar o "modo estrito"; quando true, analisa apenas formatos JSON de "objeto/matriz" (rejeitando strings/números/booleanos individuais); quando false permite analisar valores individuais |
tipo |
Texto/Array/Função | 'application/json' |
Especifica o cabeçalho Content-Type da requisição a ser analisado; pode ser string, array ou função de verificação personalizada |
verificar |
Função | undefined |
Função de verificação para validar o corpo da requisição; recebe (req, res, buf, encoding) como parâmetros, lançando erro para rejeitar a requisição |
Exemplos de Configuração
(1) Limitar tamanho do corpo da requisição
// Limita corpo da requisição a 2MB
app.use(express.json({ limite: '2mb' }));
(2) Desativar modo estrito, permitindo analisar valores JSON individuais
app.use(express.json({ estrito: false }));
// Agora pode analisar {"nome":"joao"} (objeto) e também "hello" (string)/123 (número)
app.post('/api/teste', (req, res) => {
console.log(req.body); // Se corpo for "hello", req.body será "hello"
res.send(req.body);
});
(3) Usar reviver para converter strings de data em objetos Date
app.use(express.json({
reviver: (chave, valor) => {
// Corresponde a strings de data no formato ISO (como "2025-12-19T08:00:00.000Z")
if (typeof valor === 'string' && /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/.test(valor)) {
return new Date(valor);
}
return valor;
}
}));
app.post('/api/data', (req, res) => {
console.log('Valor original:', req.body.aniversario); // Originalmente string, agora objeto Date
console.log('Data formatada:', req.body.aniversario.toLocaleDateString());
res.json({ aniversario: req.body.aniversario });
});
(4) Personalizar Content-Type analisado
Padrão analisa apenas Content-Type: application/json. Para analisar tipos personalizados (como application/vnd.meuapp+json):
// Método 1: string
app.use(express.json({ tipo: 'application/vnd.meuapp+json' }));
// Método 2: array (suporta múltiplos tipos)
app.use(express.json({ tipo: ['application/json', 'application/vnd.meuapp+json'] }));
// Método 3: função de verificação personalizada (retorna true para analisar)
app.use(express.json({
tipo: (req) => {
// Corresponde a todos os Content-Type terminados em "json"
return req.headers['content-type']?.endsWith('json');
}
}));
(5) Usar verificar para validar corpo da requisição
app.use(express.json({
verificar: (req, res, buf, encoding) => {
// buf é o Buffer de dados brutos do corpo, encoding é o formato de codificação
const corpoStr = buf.toString(encoding);
// Validação: nome de usuário deve ter pelo menos 3 caracteres
const dados = JSON.parse(corpoStr);
if (!dados.nome || dados.nome.length < 3) {
throw new Error('Nome de usuário deve ter pelo menos 3 caracteres'); // Lança erro, requisição será rejeitada
}
}
}));
// Middleware de tratamento de erro (captura erros lançados por verificar)
app.use((err, req, res, proximo) => {
res.status(400).json({ codigo: 400, mensagem: err.message });
});
Princípios Internos: Como o express.json() funciona?
O express.json() essencialmente é uma encapsulação do módulo body-parser, cujo fluxo de trabalho pode ser resumido em 5 passos:
- Verificar se precisa analisar
Primeiro, verifica se oContent-Typeda requisição corresponde ao parâmetrotipoconfigurado (padrãoapplication/json). Se não corresponder, pula diretamente sem analisar. - Processar corpo de requisição comprimido
Se o corpo da requisição estiver em formato comprimido (gzip/deflate) einflar: true, primeiro descompacta automaticamente para a string original. - Concatenar fluxo de dados do corpo
O corpo de requisição HTTP pode ser transmitido em blocos (problemas de TCP "colado/dividido"), oexpress.json()monitora o eventodatado objetoreq, concatenando gradualmente todos os blocos de dados até o eventoendser disparado (indicando conclusão da transmisão de dados). - Validação e Análise
- Valida se o tamanho do corpo excede o limite
limite, excedendo lança erro 413; - Se
estrito: true, valida se o formato JSON é objeto/matriz, caso contrário lança erro 400; - Chama
JSON.parse()(passando parâmetroreviver) para converter string JSON em objeto JS.
- Valida se o tamanho do corpo excede o limite
- Anexar a req.body
Anexa o objeto JS enalisado à propriedadereq.body, então chama o métodonext(), passando a requisição para a próxima rota/middleware.
Pseudocódigo simplificado da implementação:
function expressJson(opcoes = {}) {
// Configuração padrão
const opcoesPadrao = {
inflar: true,
limite: '100kb',
estrito: true,
tipo: 'application/json',
reviver: null
};
const opts = { ...opcoesPadrao, ...opcoes };
return (req, res, proximo) => {
// 1. Verificar se precisa analisar
const contentType = req.headers['content-type'];
if (!isMatchContentType(contentType, opts.tipo)) {
return proximo();
}
let corpoBruto = Buffer.alloc(0);
// 2. Concatenar fluxo de dados
req.on('data', (pedaco) => {
corpoBruto = Buffer.concat([corpoBruto, pedaco]);
// 3. Validar tamanho
if (corpoBruto.length > getLimitBytes(opts.limite)) {
return proximo(new Error('Payload Too Large'));
}
});
// 4. Após conclusão da transmissão de dados, analisar
req.on('end', () => {
try {
const corpoStr = corpoBruto.toString('utf8');
// Validação modo estrito
if (opts.estrito && !/^\{|\[/.test(corpoStr.trim())) {
throw new Error('Invalid JSON (modo estrito)');
}
// Análise JSON
const dadosAnalisados = JSON.parse(corpoStr, opts.reviver);
// Anexar a req.body
req.body = dadosAnalisados;
proximo();
} catch (err) {
proximo(new Error(`Invalid JSON: ${err.message}`));
}
});
};
}
Problemas Comuns e Soluções
1. Problema: req.body é undefined
Análise de Causas:
- Middleware
express.json()não registrado; - Ordem de registro incorreta do middleware (registrado após as rotas, fazendo com que as rotas executem antes da análise);
- Cabeçalho
Content-Typeda requisição do cliente não éapplication/json(ou não corresponde aotipopersonalizado); - Corpo da requisição não é JSON válido (análise falha, mas
req.bodypode ser{}ou lançar erro).
Soluções:
- Certifique-se de registrar
express.json()antes das rotas (app.use(express.json())antes deapp.post()/app.get()); - Quando enviar requisição, defina explicitamente
Content-Type: application/json; - Verifique se o corpo da requisição é JSON válido (evitar erros de sintaxe: vírgulas extras, nomes de chaves sem aspas duplas, etc.).
2. Problema: Erro 'Payload Too Large'
Análise de Causas:
O tamanho do corpo da requisição excede o limite configurado no express.json() (padrão 100kb).
Solução:
Aumente o valor do parâmetro limite:
// Aumentar para 2MB
app.use(express.json({ limite: '2mb' }));
// Ou aumentar para 10MB
app.use(express.json({ limite: '10mb' }));
3. Problema: Erro 'Invalid JSON'
Análise de Causas:
- Corpo da requisição não é JSON válido (como aspas simples em chaves, erros de sintaxe, vírgulas extras, etc.);
li>Modo estrito (
estrito: true) ativado, mas corpo da requisição é string/número/booleano individual (como"hello", 123).
Soluções:
- Corrija o formato JSON do corpo (use aspas duplas para chaves e strings, evite erros de sintaxe);
- Se precisar suportar valores JSON individuais, desative o modo estrito:
express.json({ estrito: false }).
4. Problema: Tipo de dados analisado não corresponde ao esperado
Análise de Causas:
Formato JSON não possui "tipo de data", datas são serializadas como strings, e por padrão, após análise, ainda permanecem strings, não objetos Date.
Solução:
Use o parâmetro reviver para personalizar a análise, convertendo strings de data em objetos Date (consulte o exemplo anterior em "Configuração Avançada").
5. Problema: Content-Type personalizado não é analisado
Análise de Causas:
express.json() analisa apenas application/json por padrão, e o Content-Type personalizado não foi configurado no parâmetro tipo.
Solução:
Especifique o Content-Type personalizado através do parâmetro tipo (consulte o exemplo anterior em "Configuração Avançada").
Diferenças entre outros middlewares de análise de corpo de requisição
O Express possui outros middlewares de análise de corpo de requisição integrados, sendo importante distinguir-los do express.json():
| Middleware | Função | Content-Type analisado | Cenário de uso |
|---|---|---|---|
express.json() |
Analisar corpo de requisição em formato JSON | application/json |
Projetos com separação frontend/backend (requisições AJAX/axios) |
express.urlencoded() |
Analisar corpo de requisição em formato de codificação URL | application/x-www-form-urlencoded |
Envio de formulário tradicional (formato padrão de tags form) |
express.raw() |
Analisar corpo de requisição binário bruto | Tipos personalizados (como application/octet-stream) |
Recebimento de fluxos de arquivos, dados binários |
express.text() |
Analisar corpo de requisição em texto puro | Tipos personalizados (como text/plain) |
Recebimento de strings de texto puro |
Exemplo: Registrar múltiplos middlewares de análise
// Analisar formato JSON
app.use(express.json());
// Analisar formato de codificação URL (extended: true suporta objetos aninhados)
app.use(express.urlencoded({ extended: true }));
// Analisar formato texto puro
app.use(express.text({ tipo: 'text/plain' }));
// Analisar formato binário bruto
app.use(express.raw({ tipo: 'application/octet-stream', limite: '10mb' }));