DEV Community

ToolRapido
ToolRapido

Posted on

Formatear y validar JSON en JavaScript: JSON.stringify(), errores comunes y casos límite

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');
Enter fullscreen mode Exit fullscreen mode

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'
Enter fullscreen mode Exit fullscreen mode

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
});
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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.
Enter fullscreen mode Exit fullscreen mode

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",
}
Enter fullscreen mode Exit fullscreen mode

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, RegExp y funciones no se serializan como esperas — planifica cómo manejarlos
  • structuredClone() es mejor que JSON.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)