JSON Formatter JavaScript — JSON.stringify()
Usa el Formateador y Embellecedor JSON gratuito directamente en tu navegador — sin instalación.
Probar Formateador y Embellecedor JSON online →Cuando depuro respuestas de API en Node.js, un muro de JSON minificado es lo primero que me frena — una llamada a JSON.stringify(data, null, 2) y la estructura se vuelve inmediatamente legible. Para formatear JSON en JavaScript, no necesitas nada más allá del propio entorno de ejecución: JSON.stringify está integrado en todos los navegadores y en Node.js, sin instalación alguna. Si solo necesitas un resultado rápido sin escribir código, el Formateador JSON de ToolDeck lo hace al instante. Esta guía cubre todo lo práctico: el parámetro space, arrays y funciones replacer, el manejo de Date, BigInty referencias circulares, lectura y escritura de archivos JSON en Node.js (18+), formateo desde la línea de comandos, y la librería fast-json-stringify para la serialización en producción.
- ✓JSON.stringify(data, null, 2) está integrado en todos los navegadores y Node.js — sin instalación.
- ✓El parámetro replacer acepta un array (lista blanca de claves) o una función (transformar valores) — úsalo para enmascarar campos sensibles.
- ✓Los objetos Date se serializan automáticamente mediante toJSON() → cadena ISO 8601; BigInt lanza TypeError y requiere un replacer personalizado.
- ✓Las referencias circulares lanzan TypeError — corrígelo con un Set seen en una función replacer, o usa la librería flatted.
- ✓Para formatear desde la CLI usa node -p "JSON.stringify(require('./file.json'),null,2)" — sin herramientas adicionales.
¿Qué es el formateo JSON?
El formateo JSON (también llamado pretty-printing) transforma una cadena JSON compacta y minificada en una presentación legible con sangría consistente y saltos de línea. Los datos subyacentes son idénticos — solo cambia el espacio en blanco. El JSON compacto es óptimo para la transferencia por red donde cada byte importa; el JSON formateado es óptimo para depuración, revisión de código e inspección de registros. La función JSON.stringify() de JavaScript maneja ambos casos con una sola llamada al cambiar el parámetro space.
{"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() — El formateador integrado
JSON.stringify() es una función global en todos los entornos JavaScript — navegadores, Node.js, Deno, Bun — sin necesidad de importación. Su tercer argumento, space, controla la sangría: pasa un número para ese número de espacios por nivel, o la cadena '\t' para tabulaciones. Si se omite (o se pasa null), se obtiene una salida compacta en una sola línea.
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
// }
// }El parámetro space acepta un número (1–10 espacios) o una cadena. Pasar un carácter de tabulación produce una salida que muchos editores y herramientas de diff prefieren. También puedes combinar los tres parámetros — aquí un patrón real que uso al escribir JSON formateado en archivos de configuración:
const telemetryEvent = {
eventId: "evt_3c7f9a2b",
service: "checkout-api",
severity: "warn",
latencyMs: 342,
region: "eu-west-1",
tags: ["payment", "timeout", "retry"]
}
// Sangría de 2 espacios (más común en proyectos JS)
JSON.stringify(telemetryEvent, null, 2)
// Sangría con tabulación (preferida por algunos linters y herramientas de config)
JSON.stringify(telemetryEvent, null, '\t')
// Compacto — sin espacios en blanco (para transferencia por red)
JSON.stringify(telemetryEvent)
// {"eventId":"evt_3c7f9a2b","service":"checkout-api",...}undefined, las funciones y los valores Symbol se omiten silenciosamente de la salida. Si el valor de una propiedad es undefined, esa clave no aparecerá en absoluto en la cadena serializada — es una fuente habitual de errores al registrar objetos con campos opcionales.Funciones replacer — Filtrar y transformar la salida
El segundo argumento de JSON.stringify() es el replacer. Tiene dos formas: un array que incluye solo las claves indicadas, o una función que se invoca para cada par clave/valor y puede filtrar, transformar o redactar valores. Recurro al array cuando necesito un subconjunto rápido, y a la función cuando necesito enmascarar datos sensibles antes de registrarlos.
Replacer de array — Lista blanca de claves específicas
const order = {
orderId: "ord_8f2a91bc",
customer: {
id: "usr_4421",
email: "c.mendoza@ejemplo.com",
passwordHash: "bcrypt:$2b$12$XKzV..."
},
items: [{ sku: "HDMI-4K-2M", qty: 2, unitPrice: 12.99 }],
createdAt: "2026-03-10T14:22:00Z"
}
// Solo incluir campos seguros en el 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 y customer.email quedan excluidosReplacer de función — Transformar valores
const auditRecord = {
requestId: "req_7d2e91",
user: { id: "usr_4421", email: "c.mendoza@ejemplo.com", apiKey: "sk-live-eKx9..." },
action: "update_billing",
timestamp: new Date("2026-03-10T14:22:00Z"),
durationMs: 87
}
function safeReplacer(key, value) {
// Redactar campos que parecen secretos o PII
if (key === "apiKey") return "[REDACTADO]"
if (key === "email") return value.replace(/(?<=.{2}).+(?=@)/, "***")
return value
}
console.log(JSON.stringify(auditRecord, safeReplacer, 2))
// {
// "requestId": "req_7d2e91",
// "user": { "id": "usr_4421", "email": "c.***@ejemplo.com", "apiKey": "[REDACTADO]" },
// "action": "update_billing",
// "timestamp": "2026-03-10T14:22:00.000Z",
// "durationMs": 87
// }this establecido en el objeto que contiene la clave actual. La primera llamada pasa una cadena vacía como clave y el valor completo que se está serializando como valor — devuélvelo sin cambios para continuar con la serialización normal.Manejo de tipos no serializables
No todos los valores de JavaScript se corresponden limpiamente con JSON. Conocer el comportamiento de cada tipo evita pérdidas silenciosas de datos y errores inesperados en producción.
Date — Automático mediante toJSON()
Los objetos Date implementan un método toJSON() que devuelve una cadena ISO 8601. JSON.stringify() llama a toJSON() automáticamente antes de serializar, por lo que no se requiere ningún manejo personalizado.
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"
// }
// Cualquier objeto con un método toJSON() recibe el mismo trato:
const custom = { toJSON: () => "valor-personalizado", hidden: 42 }
JSON.stringify(custom) // '"valor-personalizado"'Clases personalizadas — Implementar toJSON()
Cualquier clase puede implementar un método toJSON() y JSON.stringify() lo llamará automáticamente durante la serialización. Esto es más limpio que un replacer global para tipos de dominio que aparecen en todo el código.
class Money {
constructor(amount, currency) {
this.amount = amount
this.currency = currency
}
toJSON() {
// Llamado automáticamente 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 cadena simple
}
const invoice = {
invoiceId: new OrderId('inv_8f2a91bc'),
subtotal: new Money(199.00, 'USD'),
tax: new Money(15.92, 'USD'),
issuedAt: new Date('2026-03-10T14:22:00Z')
}
JSON.stringify(invoice, null, 2)
// {
// "invoiceId": "inv_8f2a91bc",
// "subtotal": { "amount": 199, "currency": "USD", "formatted": "USD 199.00" },
// "tax": { "amount": 15.92, "currency": "USD", "formatted": "USD 15.92" },
// "issuedAt": "2026-03-10T14:22:00.000Z"
// }toJSON() tiene prioridad sobre la función replacer. Si ambos están presentes, toJSON() se ejecuta primero — el replacer recibe el valor ya convertido, no la instancia de clase original.BigInt — TypeError sin un replacer
// Esto lanza: TypeError: Do not know how to serialize a BigInt
// JSON.stringify({ sessionId: 9007199254741234n })
// Solución: convertir BigInt a string en el replacer
function bigIntReplacer(_key, value) {
return typeof value === 'bigint' ? value.toString() : value
}
const metrics = {
requestCount: 9007199254741234n, // supera 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"
// }Referencias circulares — TypeError sin un Set seen
// Esto lanza: TypeError: Converting circular structure to JSON
// const node = { id: "n1" }; node.self = node; JSON.stringify(node)
// Solución: rastrear objetos vistos con un 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) // gestiona refs circulares de forma nativaReferencia de parámetros de JSON.stringify()
Los tres parámetros tienen soporte completo en todos los entornos JavaScript modernos. Los valores por defecto producen JSON compacto en una sola línea — pasa los parámetros explícitamente para obtener una salida legible.
Formatear JSON desde un archivo y una respuesta de API
En Node.js (18+) a menudo necesitas reformatear un archivo de configuración JSON o mostrar con formato una respuesta de API para depuración. Ambos patrones usan el mismo enfoque de dos pasos: analizar el texto crudo con JSON.parse() y luego volver a serializarlo con JSON.stringify().
Leer y reescribir un archivo de configuración JSON
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 reformateado correctamente')
} catch (err) {
console.error('Error al reformatear config:', err.message)
// JSON.parse lanza SyntaxError si el archivo contiene JSON inválido
// readFileSync lanza ENOENT si el archivo no existe
}Reformateo asíncrono de archivo (fs/promises)
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(`Reformateadas ${keys} claves de nivel superior`)Mostrar con formato JSON de una respuesta fetch()
Al construir o depurar un cliente de API en Node.js 18+ o el navegador, formatear el cuerpo de la respuesta es la forma más rápida de entender lo que devolvió el servidor. El patrón estándar es response.json() (objeto analizado) pasado a JSON.stringify(). Si necesitas la cadena cruda primero — por ejemplo para calcular un hash o registrarla literalmente — usa response.text() y luego JSON.parse().
// Patrón 1: response.json() → mostrar con 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')// Patrón 2: response.text() → analizar → formatear
// Útil cuando quieres registrar la respuesta cruda Y mostrarla con formato
async function inspectRawResponse(url) {
const res = await fetch(url)
const raw = await res.text()
console.log('Longitud de la respuesta cruda:', raw.length)
try {
const parsed = JSON.parse(raw)
console.log('Formateado:')
console.log(JSON.stringify(parsed, null, 2))
} catch {
console.error('La respuesta no es JSON válido:', raw.slice(0, 200))
}
}Formateo desde la línea de comandos
Node.js incluye suficiente capacidad para formatear JSON desde el terminal sin herramientas adicionales. Estos one-liners son útiles en scripts de CI, pipelines de despliegue y alias de shell. Para un uso interactivo aún más rápido, instala jq — el estándar de facto para la manipulación de JSON en línea de comandos.
# Formatear package.json usando node -p (print)
node -p "JSON.stringify(require('./package.json'), null, 2)"
# Formatear desde stdin (compatible con pipes, funciona en CI)
echo '{"port":3000,"env":"production"}' | node -e "
const d = require('fs').readFileSync(0, 'utf8')
console.log(JSON.stringify(JSON.parse(d), null, 2))
"
# Formatear una respuesta de API guardada en un archivo
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)))
"# Alternativa con Python (preinstalado en macOS y la mayoría de Linux)
cat api-response.json | python3 -m json.tool
# jq — más rápido y con más funcionalidades (brew install jq / apt install jq)
cat api-response.json | jq .
# jq — formatear y filtrar en un solo paso
cat api-response.json | jq '.data.users[] | {id, email}'"type": "module" en package.json), require() no está disponible en one-liners. Usa --input-type=module y fs.readFileSync en su lugar, o cambia a node -e con un fragmento CommonJS como se muestra arriba.Si no estás en la terminal — pegando una respuesta de Postman o un archivo de logs — el Formateador JSON de ToolDeck te permite pegar, formatear y copiar en un solo paso con resaltado de sintaxis y validación integrada.
Alternativa de alto rendimiento — fast-json-stringify
fast-json-stringify genera una función serializadora dedicada a partir de un JSON Schema. Como conoce la forma de los datos de antemano, puede omitir la verificación de tipos y usar concatenación de cadenas en lugar de descenso recursivo — los benchmarks suelen mostrar una mejora de rendimiento de 2–5× respecto a JSON.stringify() en payloads grandes y repetitivos. Lo uso en rutas de API de alta frecuencia donde el coste de serialización aparece en los perfiles de rendimiento.
npm install fast-json-stringify
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",...}'fast-json-stringify está diseñado para la serialización en producción de datos estructurados — siempre produce salida compacta (sin formato legible). Para salida legible durante el desarrollo, usa JSON.stringify(data, null, 2) con normalidad.Salida de terminal con resaltado de sintaxis
La función integrada de Node.js util.inspect() produce una salida con colores y legible optimizada para la visualización en terminal. Gestiona las referencias circulares y BigInt de forma nativa, y renderiza recursivamente objetos anidados a cualquier profundidad. La salida no es JSON válido — usa sintaxis JavaScript (p. ej. true en lugar de true, pero renderiza funciones y Symbols en lugar de omitirlos), lo que lo hace ideal para scripts de depuración en Node.js pero no apto para respuestas de API o salida a archivo.
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 los niveles anidados; colors: true → colores ANSI de terminal
console.log(inspect(payload, { colors: true, depth: null }))util.inspect() para JSON escrito en archivos, enviado por la red o almacenado en una base de datos. Su salida no es JSON válido y causará errores de análisis en cualquier sistema downstream que llame a JSON.parse() sobre ella. Resérvala exclusivamente para la depuración interactiva en terminal.Trabajar con archivos JSON grandes
JSON.parse() carga todo el archivo en memoria antes de analizarlo — correcto para payloads pequeños, pero impracticable para archivos de más de 50–100 MB como exportaciones de bases de datos, volcados de registros de aplicaciones o lotes de análisis. Para estos casos, los Streams de Node.js y la librería stream-json permiten procesar registros uno a uno sin saturar el heap.
Análisis en streaming con stream-json
npm install stream-json
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 millones de objetos — nunca se carga completamente en memoria
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 — Sin dependencias adicionales
NDJSON (Newline Delimited JSON) almacena un objeto JSON por línea y es común en exportaciones de Kafka, salidas de BigQuery y pipelines de registros estructurados. El módulo integrado readline de Node.js lo gestiona sin paquetes de terceros.
import { createReadStream } from 'fs'
import { createInterface } from 'readline'
// Formato: un objeto JSON por línea (logs, exportaciones de 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))
}
}JSON.parse() al streaming cuando tu archivo JSON supere los 50–100 MB o cuando proceses un flujo ilimitado (Kafka, pipeline de logs). Para NDJSON / JSON Lines, usa readline — no requiere dependencias adicionales.Errores comunes
Estos cuatro errores aparecen repetidamente en revisiones de código e informes de bugs en producción. Cada uno implica un comportamiento sutil de JSON.stringify() que es fácil pasar por alto y difícil de depurar después del hecho.
Problema: Las propiedades de objeto con valores undefined se omiten completamente de la salida JSON — sin advertencia ni error. Esto provoca una pérdida invisible de datos cuando existen campos opcionales en el objeto.
Solución: Usa null para los valores intencionalmente ausentes que deben aparecer en la salida serializada. Reserva undefined solo para los campos que deben excluirse del JSON.
const userProfile = {
userId: "usr_4421",
displayName: "Carlos Mendoza",
avatarUrl: undefined, // desaparecerá silenciosamente
bio: undefined // desaparecerá silenciosamente
}
JSON.stringify(userProfile, null, 2)
// { "userId": "usr_4421", "displayName": "Carlos Mendoza" }
// avatarUrl y bio han desaparecido — sin advertenciaconst userProfile = {
userId: "usr_4421",
displayName: "Carlos Mendoza",
avatarUrl: null, // ausente de forma explícita — aparece en la salida
bio: null // ausente de forma explícita — aparece en la salida
}
JSON.stringify(userProfile, null, 2)
// {
// "userId": "usr_4421",
// "displayName": "Carlos Mendoza",
// "avatarUrl": null,
// "bio": null
// }Problema: Pasar un valor BigInt a JSON.stringify() lanza un TypeError en tiempo de ejecución. Es un fallo total, no una omisión silenciosa — aparecerá en producción si algún campo numérico supera Number.MAX_SAFE_INTEGER.
Solución: Usa una función replacer que convierta los valores BigInt a cadenas antes de la serialización. Alternativamente, convierte BigInt a string o Number en la capa de datos antes de pasarlo a JSON.stringify.
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 BigIntfunction 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"
// }Problema: Los objetos que se referencian a sí mismos — habituales en árboles DOM, listas enlazadas y algunos conjuntos de resultados de ORM — lanzan un TypeError al pasarlos a JSON.stringify(). El error solo ocurre en el momento de la serialización, a menudo lejos de donde se creó la referencia circular.
Solución: Usa una función replacer con un WeakSet para detectar y reemplazar las referencias circulares, o instala la librería flatted como reemplazo directo que gestiona estructuras circulares de forma nativa.
const dept = { id: "dept_eng", name: "Ingeniería" }
const team = { id: "team_frontend", dept }
dept.teams = [team] // circular: dept → team → dept
JSON.stringify(dept, null, 2)
// Uncaught TypeError: Converting circular structure to JSONimport { stringify } from 'flatted' // npm install flatted
const dept = { id: "dept_eng", name: "Ingeniería" }
const team = { id: "team_frontend", dept }
dept.teams = [team]
// flatted gestiona refs circulares — nota: la salida es formato flatted, no JSON estándar
stringify(dept)
// O usa un replacer basado en WeakSet si necesitas JSON estándar:
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)Problema: Pasar un valor de space mayor que 10 a JSON.stringify() no lanza un error — el valor se limita silenciosamente a 10. Los desarrolladores que esperan 20 espacios por nivel de sangría para estructuras profundas obtendrán solo 10, lo que lleva a un formato inesperado en los archivos generados.
Solución: La sangría máxima es de 10 espacios. Para estructuras profundas, prefiere una sangría de 2 espacios (la convención más común en proyectos JavaScript) y confía en editores con colapso para la navegación.
const deepConfig = { server: { tls: { certs: { primary: "/etc/ssl/api.pem" } } } }
// Se espera una sangría de 20 espacios — pero space se limita a 10
JSON.stringify(deepConfig, null, 20)
// Misma salida que JSON.stringify(deepConfig, null, 10)
// Sin error, sin advertencia — truncado silenciosamenteconst deepConfig = { server: { tls: { certs: { primary: "/etc/ssl/api.pem" } } } }
// Usa 2 (la mayoría de proyectos) o 4 espacios — nunca superes 10
JSON.stringify(deepConfig, null, 2)
// {
// "server": {
// "tls": {
// "certs": {
// "primary": "/etc/ssl/api.pem"
// }
// }
// }
// }JSON.stringify vs alternativas — Comparación rápida
Diferentes situaciones requieren diferentes herramientas. JSON.stringify con un replacer cubre la mayoría de casos de uso en producción sin dependencias. util.inspect es la elección correcta para la depuración rápida en terminal cuando necesitas salida con colores y no necesitas JSON válido. fast-json-stringify vale la pena en rutas de alto rendimiento donde el perfil muestra que la serialización tiene coste; para todo lo demás, la sobrecarga del mantenimiento del esquema no merece la pena.
Preguntas frecuentes
¿Cómo formateo JSON con sangría en JavaScript?
Llama a JSON.stringify(data, null, 2): el tercer argumento controla la sangría. Pasa 2 o 4 para espacios, o "\t" para tabulaciones. No se necesita ninguna importación ni instalación: JSON es un objeto global en todos los entornos JavaScript, incluidos navegadores y Node.js.
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
// }¿Qué hace el parámetro `space` en JSON.stringify()?
El parámetro space controla la sangría de la salida. Pasa un número (1–10) para tantos espacios por nivel, o una cadena como "\t" para usar un carácter de tabulación. Los valores superiores a 10 se limitan silenciosamente a 10. Pasar null, 0 u omitir el parámetro produce un JSON compacto en una sola línea.
const data = { service: "payments", version: 3, active: true }
JSON.stringify(data, null, 2) // sangría de 2 espacios
JSON.stringify(data, null, 4) // sangría de 4 espacios
JSON.stringify(data, null, '\t') // sangría con tabulación
JSON.stringify(data) // compacto: {"service":"payments","version":3,"active":true}¿Por qué JSON.stringify() devuelve undefined para algunos valores?
JSON.stringify omite silenciosamente las propiedades de objetos cuyos valores son undefined, funciones o Symbols, ya que estos tipos no tienen representación en JSON. Si el valor de nivel superior es undefined, la función devuelve undefined (no la cadena "undefined"). Usa null en lugar de undefined para los campos opcionales que deben aparecer en la salida.
const event = {
traceId: "tr_9a2f",
handler: () => {}, // función — se omite
requestId: undefined, // undefined — se omite
sessionId: Symbol("s"), // Symbol — se omite
status: "ok"
}
JSON.stringify(event, null, 2)
// { "traceId": "tr_9a2f", "status": "ok" }¿Cómo manejo objetos Date al formatear JSON?
Los objetos Date tienen un método toJSON() integrado que devuelve una cadena ISO 8601, por lo que JSON.stringify los gestiona automáticamente. No necesitas un replacer personalizado para fechas: el valor serializado será una cadena como "2026-03-10T14:22:00.000Z".
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
// }¿Cómo formateo una cadena JSON (no un objeto) en JavaScript?
Primero analiza la cadena con JSON.parse() y luego vuelve a serializarla con JSON.stringify(). Ambas llamadas se pueden encadenar en una sola línea para depuración rápida.
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
// }¿Puedo usar JSON.stringify() en el navegador?
Sí. JSON es un objeto global integrado en todos los navegadores modernos desde IE8: no se necesitan etiquetas de script ni importaciones. Abre la consola de DevTools y llama a JSON.stringify() directamente. Funciona de forma idéntica a la versión de Node.js, con la misma firma de parámetros y las mismas limitaciones respecto a BigInt y referencias circulares.
// Funciona en Chrome, Firefox, Safari, Edge — sin importaciones
const payload = { userId: "usr_7b3c", action: "checkout", cart: ["SKU-001", "SKU-002"] }
copy(JSON.stringify(payload, null, 2)) // copy() es un helper de DevToolsJavaScript te da control total — funciones replacer, toJSON() personalizado, procesamiento de archivos grandes en Node.js. Cuando solo necesitas inspeccionar o compartir un fragmento formateado, el Formateador JSON de ToolDeck es el camino más rápido: pega tu JSON y obtén un resultado formateado y resaltado sin configurar ningún entorno.
Herramientas relacionadas
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.
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.