JSON es el formato de intercambio de datos más usado en desarrollo web. Pero JSON.stringify() y JSON.parse() tienen matices que sorprenden incluso a desarrolladores con años de experiencia.
Formateo con indentación
const data = { name: 'ToolRapido', tools: ['NIF', 'QR', 'UUID'], active: true };
// Compacto (por defecto)
JSON.stringify(data);
// '{"name":"ToolRapido","tools":["NIF","QR","UUID"],"active":true}'
// Indentado con 2 espacios
JSON.stringify(data, null, 2);
// {
// "name": "ToolRapido",
// "tools": ["NIF", "QR", "UUID"],
// "active": true
// }
// Indentado con tabuladores
JSON.stringify(data, null, '\t');
Validar JSON sin try/catch en cada sitio
function isValidJSON(str) {
try {
JSON.parse(str);
return true;
} catch {
return false;
}
}
// Versión que devuelve el error
function parseJSON(str) {
try {
return { ok: true, data: JSON.parse(str) };
} catch (err) {
return { ok: false, error: err.message };
}
}
const result = parseJSON('{"broken": json}');
result.ok; // false
result.error; // 'Unexpected token j in JSON at position 12'
Tipos que JSON.stringify() ignora o transforma
Esto sorprende a muchos:
JSON.stringify({
fn: () => {}, // undefined (se omite)
sym: Symbol('x'), // undefined (se omite)
undef: undefined, // undefined (se omite)
nan: NaN, // null
inf: Infinity, // null
date: new Date(), // string ISO
regexp: /regex/, // {} ← TRAMPA
map: new Map([['a', 1]]), // {} ← TRAMPA
set: new Set([1, 2]), // [] ← TRAMPA
});
Para serializar Map y Set:
function replacer(key, value) {
if (value instanceof Map) {
return { __type: 'Map', entries: [...value.entries()] };
}
if (value instanceof Set) {
return { __type: 'Set', values: [...value] };
}
return value;
}
function reviver(key, value) {
if (value?.__type === 'Map') return new Map(value.entries);
if (value?.__type === 'Set') return new Set(value.values);
return value;
}
const data = { myMap: new Map([['a', 1]]) };
const json = JSON.stringify(data, replacer, 2);
const back = JSON.parse(json, reviver);
back.myMap instanceof Map; // true
El replacer para filtrar campos
// Solo incluir campos específicos
JSON.stringify(user, ['name', 'email'], 2);
// Excluir campos sensibles
function omitSensitive(key, value) {
const sensitive = ['password', 'token', 'secret'];
if (sensitive.includes(key)) return undefined;
return value;
}
JSON.stringify(user, omitSensitive, 2);
Clonar objetos con JSON
// Forma rápida (limitada — pierde funciones, fechas, etc.)
const clone = JSON.parse(JSON.stringify(obj));
// Forma moderna y correcta
const clone = structuredClone(obj); // soporta Date, Map, Set, etc.
structuredClone() está disponible en Node 17+ y todos los navegadores modernos.
Diferencias entre JSON y JSON5
JSON5 es un superconjunto de JSON que permite comentarios, comas finales y más:
{
// Comentarios
name: 'sin comillas en keys',
trailing: 'coma',
hex: 0xFF,
multiline: "primera línea \
segunda línea",
}
JSON5 es útil para archivos de configuración pero no para APIs (usar siempre JSON estándar en APIs).
Herramienta online
Si necesitas formatear o validar un JSON rápidamente durante el desarrollo, puedes usar este formateador de JSON gratuito que funciona en el navegador con resaltado de errores.
Conclusión
- Usa
JSON.stringify(data, null, 2)para formateo legible -
Map,Set,RegExpy funciones no se serializan como esperas — planifica cómo manejarlos -
structuredClone()es mejor queJSON.parse(JSON.stringify())para clonar objetos - Centraliza el parseo en una función que devuelva
{ ok, data, error }para manejar errores limpiamente
Top comments (0)