Cómo construir un formateador de JSON en JavaScript puro
JSON.parse y JSON.stringify hacen el trabajo pesado. Lo interesante está en los detalles: extraer la posición del error, calcular línea y columna, y sincronizar dos áreas de texto.

Un formateador de JSON suena trivial: parseas, stringificas con sangría, listo. Y en su forma más básica lo es. Pero en cuanto intentas dar feedback útil al usuario —dónde falla exactamente, cuántos niveles tiene, qué tipo de dato es la raíz— hay suficiente chicha para que valga la pena documentarlo.
El núcleo: parse y stringify
JavaScript tiene todo lo necesario de serie. Para validar y formatear:
try {
var parsed = JSON.parse(input);
var formateado = JSON.stringify(parsed, null, 2);
} catch (err) {
// error de sintaxis
}
El segundo argumento de JSON.stringify es un replacer (aquí null, sin filtrado). El tercero es la sangría: 2 da dos espacios por nivel, 4 da cuatro, '\t' usa tabuladores.
Para minificar es lo mismo sin el tercer argumento:
var minificado = JSON.stringify(parsed);
Extraer línea y columna del error
Cuando JSON.parse lanza un SyntaxError, el mensaje incluye la posición del carácter problemático: Unexpected token } at position 42. Esa posición es un offset de carácter desde el inicio del string.
Convertirla a línea y columna es aritmética de strings:
function parsearError(err, input) {
var msg = err.message || '';
var posMatch = msg.match(/position (\d+)/i);
if (!posMatch) return msg;
var pos = parseInt(posMatch[1], 10);
var antes = input.slice(0, pos);
var linea = (antes.match(/\n/g) || []).length + 1;
var col = pos - antes.lastIndexOf('\n');
return 'Error en línea ' + linea + ', columna ' + col;
}
antes.lastIndexOf('\n') devuelve -1 si no hay saltos de línea, lo que hace que col sea pos + 1 —exactamente lo correcto para la primera línea.
Detectar el tipo raíz y contar claves
Un JSON válido puede ser cualquier valor: objeto, array, string, número, booleano o null. Mostrar el tipo al usuario ayuda a confirmar que ha pegado lo correcto:
var tipo = Array.isArray(parsed) ? 'Array'
: parsed === null ? 'null'
: typeof parsed;
Para contar claves en objetos anidados, una función recursiva:
function contarClaves(obj) {
if (obj === null || typeof obj !== 'object') return 0;
return Object.keys(obj).length
+ Object.values(obj).reduce(function(acc, v) {
return acc + contarClaves(v);
}, 0);
}
Y la profundidad máxima de anidamiento, que da una idea de la complejidad:
function profundidadMax(obj, nivel) {
nivel = nivel || 0;
if (obj === null || typeof obj !== 'object') return nivel;
var hijos = Object.values(obj).map(function(v) {
return profundidadMax(v, nivel + 1);
});
return hijos.length ? Math.max.apply(null, hijos) : nivel;
}
Copiar al portapapeles
La API moderna es navigator.clipboard.writeText(), que devuelve una promesa. Merece un fallback al método antiguo porque algunos contextos (HTTP sin localhost, iframes de ciertos orígenes) la tienen restringida:
function copiar(texto) {
if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard.writeText(texto);
return;
}
// fallback para contextos sin permisos de clipboard
var tmp = document.createElement('textarea');
tmp.value = texto;
tmp.style.position = 'fixed';
tmp.style.opacity = '0';
document.body.appendChild(tmp);
tmp.select();
document.execCommand('copy');
document.body.removeChild(tmp);
}
Sincronizar entrada y salida
El patrón es un único listener en el textarea de entrada que actualiza todo lo demás: el estado de validación, el textarea de salida y el estado habilitado/deshabilitado de los botones de copia. Una sola fuente de verdad:
inputEl.addEventListener('input', function () {
var raw = inputEl.value;
if (!raw.trim()) { resetear(); return; }
try {
var parsed = JSON.parse(raw);
outputEl.value = JSON.stringify(parsed, null, 2);
mostrarExito(parsed);
habilitarBotones(true);
} catch (err) {
outputEl.value = '';
mostrarError(err, raw);
habilitarBotones(false);
}
});
No hace falta debounce: JSON.parse de JSONs razonablemente grandes (cientos de KB) es instantáneo en cualquier motor moderno.
A continuación puedes probar la herramienta completa.
Formateador de JSON
Pega tu JSON para validarlo al instante. Obtendrás la versión formateada con sangría y los errores de sintaxis indicados con precisión.


