Un formateador JSON (formatter / beautifier / pretty printer / validator) no es decoracion — es infraestructura de legibilidad para depurar APIs, gestionar archivos de configuracion, intercambio de datos y decodificacion de payloads JWT. El habito de formateo de la mayoria de los desarrolladores es “presionar el atajo de formato del IDE”, lo que resuelve el 30% del problema. El 70% restante (comas finales, escape Unicode, perdida de precision en enteros grandes, caracteres BOM, comillas simples, serializacion de NaN / Infinity / undefined, efectos secundarios de ordenar claves) no se puede resolver con el IDE.

El valor principal de un formateador JSON no es “hacer que el JSON se vea bonito” — es hacer que los datos sean legibles por humanos durante la depuracion de APIs, revision de configuracion, analisis de logs, decodificacion de JWT. Eso es infraestructura, no embellecimiento. Este articulo cubre 8 errores reales en formato “sintoma + por que + como arreglar”, luego presenta el Formateador JSON Piick — resaltado de sintaxis + ordenar claves + parseo tolerante (JSON5 / comillas simples / comentarios) + clic-para-saltar a posicion de error + 5 metricas (claves / arrays / profundidad maxima de anidamiento / bytes), 100% local, todo en 1 minuto.

Resumen en 30 Segundos

  • Formateo JSON != embellecimiento: el primero es infraestructura de legibilidad para API / configuracion / inspeccion de logs; el segundo es solo “hacer que el codigo se vea ordenado”
  • El estandar JSON tiene 4 restricciones duras: comas finales no permitidas, las cadenas deben usar comillas dobles, comentarios no permitidos, NaN / Infinity / undefined no permitidos (4 errores obligatorios)
  • 3 usos incorrectos comunes del ecosistema JS: coma final (legal en ES2017+), objetos literales con comillas simples, cadenas de plantilla anidadas en JSON (desastre de escape)
  • 8 errores comunes: coma final / escape Unicode / precision de enteros grandes / indentacion != anidamiento / caracteres BOM / comillas simples / serializacion NaN-Infinity-undefined / efecto secundario de ordenar claves
  • Direccion de la correccion: siempre valida con una herramienta (especialmente la configuracion de API de produccion), siempre parseo tolerante (desarrollo), siempre preserva enteros grandes como cadenas (Snowflake ID), nunca ordena claves automaticamente (afecta Git diff)
  • Usa el Formateador JSON Piick en linea para formatear / validar / embellecer, parseo tolerante + resaltado de sintaxis + clic-para-saltar a posicion de error + 5 metricas, todo procesado en local

8 Errores Comunes

Error 1: Coma Final Rechazada por el Estandar JSON

Sintoma: Desde Chrome DevTools “Copy as fetch”, copias el cuerpo de la respuesta, pegas en el formateador JSON y reporta “Unexpected token”. Piensas que es un bug de la herramienta — en realidad el JSON copiado por DevTools tiene coma final (coma extra despues de la ultima clave), que el estandar JSON no permite.

Por que: ECMAScript 2017+ permite comas finales en literales de objeto, asi que el JSON copiado por Chrome / Firefox DevTools a menudo incluye una coma final. Los diccionarios de Python 3.7+ tambien lo permiten. La especificacion JSON RFC 8259 seccion 5 establece claramente “trailing commas are not allowed”. El JSON.parse ingenuo sigue estrictamente la especificacion, ve {"a": 1,} y reporta error.

Arreglo: El JSON de produccion no debe tener comas finales. En desarrollo puedes usar la opcion “parseo tolerante” de la herramienta (Formateador JSON Piick soporta estilo JSON5, aceptando coma final + comillas simples + comentarios), pero debe ser lint antes de commit a archivos de API / configuracion. CI ejecuta prettier --check o eslint --rule no-trailing-commas como red de seguridad.

Escenario real: Frontend hace fetch a la API del backend, Chrome DevTools “Copy as fetch”, pegas a jq .response.users[0].id, falla. Razon: la salida de DevTools tiene coma final, jq es parseo estricto. Siempre lint antes de jq, o usa directamente el modo tolerante de jq jq -R ..

Error 2: Caracteres Unicode Sin Escapar

Sintoma: El backend devuelve {"name":"张三"}, el frontend JSON.parse funciona bien. Pero a veces los mismos datos pegados en una herramienta reportan “Unexpected token”, o algunas librerias al hacer stringify tienen el chino convertido a ?. Esto es escape Unicode inconsistente.

Por que: La especificacion JSON establece los caracteres no-ASCII en cadenas pueden aparecer directamente como UTF-8 (porque el documento JSON en si requiere UTF-8), y tambien pueden ser escapados como \uXXXX. Ambos formatos son legales. Pero el comportamiento por defecto de algunas librerias difiere:

  • Python json.dumps por defecto ensure_ascii=True, escapando todo lo no-ASCII a \uXXXX
  • JavaScript JSON.stringify por defecto preserva el Unicode original
  • Java ObjectMapper por defecto escapa
  • Go encoding/json por defecto escapa

El backend en Python produce {"name":"\u5f20\u4e09"}, el frontend en JS parsea a 张三, pero si copias la respuesta cruda del backend a vim para compartir con un companero, el companero ve {"name":"\u5f20\u4e09"} confundido. Esta es la inconsistencia entre UTF-8 y escape \u.

Arreglo: Asegurate siempre de que el JSON de produccion sea UTF-8. El backend en Python usa json.dumps(..., ensure_ascii=False) para formato legible (con Content-Type: application/json; charset=utf-8). Al depurar, usa el parseo tolerante de la herramienta, tratando \uXXXX como entrada legal.

Escenario real: El backend en Python hace dump {"msg":"\u4f60\u597d"}, el frontend fetch y response.json() obtiene {msg:"你好"}, correcto. Pero si copias la respuesta cruda del backend a vim, le das a un companero, el companero ve {"msg":"\u4f60\u597d"} confundido. Esta es la inconsistencia entre UTF-8 y escape \u.

Error 3: Perdida de Precision en Enteros Grandes (Ultimos Bits del Snowflake ID se Convierten en 0)

Sintoma: El backend devuelve {"user_id": 1234567890123456789}, el frontend JSON.parse hace que user_id sea 1234567890123456800, los ultimos 3 digitos son todos 0. El ID del backend es correcto, el ID extraido por el frontend es incorrecto, la consulta a la base de datos da 404.

Por que: El Number de JavaScript es IEEE 754 de doble precision, el rango de enteros seguros es 2^53 − 1 = 9007199254740991 (aproximadamente 9 × 10^15). Los enteros que exceden este rango pierden precision. El Snowflake ID es un entero de 19 digitos (aproximadamente 10^18), JSON.parse pierde precision directamente. El int de Python / long de Java no tienen este problema, pero JS es el lenguaje frontend mas comun.

Arreglo:

  • Backend: serializa bigint como cadena ("1234567890123456789"), no numero
  • Frontend: usa la libreria json-bigint al parsear, o maneja todo como cadenas
  • Visualizacion: al mostrar UI, BigInt(id).toString(), al calcular usa tipo bigint
  • Diseno de API: al devolver ID, considera directamente UUID (36 chars) o ULID (26 chars), ambos formato cadena

Al validar respuesta de API con el Formateador JSON Piick, primero verifica el placeholder, pega y verifica que la salida coincida; si la longitud del ID > 15 digitos, alerta por problemas de precision en enteros grandes.

Escenario real: El Snowflake ID de Twitter es un entero de 64 bits, aproximadamente 1770000000000000000, muy por encima de 2^53. El frontend hace fetch del tweet id 1234567890123456789, en realidad obtiene 1234567890123458000, no lo encuentra. El Snowflake ID debe serializarse como cadena.

Error 4: Indentacion != Estructura de Anidamiento

Sintoma: Tu codigo usa indentacion de 2 espacios, el de tu companero usa 4 espacios, la revision del PR parece JSON completamente diferente, pero el resultado del parseo es exactamente el mismo. Piensas que es diferente profundidad de anidamiento, en realidad {"a":{"b":{"c":1}}} y {"a": { "b": { "c": 1 } }} son el mismo objeto.

Por que: La sintaxis JSON no se preocupa por espacios en blanco, siempre que se cumplan las reglas lexicas de RFC 8259, cualquier numero de espacios / tabs / saltos de linea es equivalente. La indentacion es solo “legibilidad para el ojo humano”, no tiene nada que ver con el anidamiento real. Esta es tambien la la razon por la que los archivos JSON en git diff parecen que todo cambio cuando agregas/eliminas un solo campo (porque la indentacion se reordena).

Arreglo: Unifica el estilo de indentacion (recomienda 2 espacios, ahorra ancho de linea) + usa prettier / jq para auto-formateo, evita el formateo manual. Usa la opcion “indent” de la herramienta (Formateador JSON Piick soporta 2 espacios / 4 espacios / tab / minify), equipo unificado.

Escenario real: Configuracion JSON con 100 campos, 2 espacios vs 4 espacios:

  • 2 espacios: {"a":1,"b":2,"c":{"d":3}} compacto
  • 4 espacios: {"a": 1, "b": 2, "c": { "d": 3 }} amplio

5+ niveles de anidamiento, 4 espacios por nivel, 5 niveles = 20 caracteres de margen izquierdo, pantalla de 80 caracteres solo tiene 60 caracteres de contenido. 2 espacios mejor para anidamiento profundo.

Error 5: Caracteres BOM Ignorados

Sintoma: El archivo JSON se ve normal en VSCode, pegas a la herramienta / Node.js JSON.parse reporta error “Unexpected token”. Click derecho → Ver Codificacion → UTF-8 with BOM. Razon: el archivo tiene un caracter invisible \ufeff (BOM, byte order mark) al principio.

Por que: Windows Notepad / algunos editores antiguos guardan archivos UTF-8 con BOM por defecto (3 bytes EF BB BF). JS / Python / la mayoria de los parsers JSON ven \ufeff como token JSON y reportan error. La especificacion JSON no permite BOM en el texto JSON (excepto dentro de cadenas del documento JSON, como caracter de escape).

Arreglo:

  • Guardar sin BOM: VSCode esquina inferior derecha → UTF-8 with BOM → UTF-8 (por defecto)
  • Transcoding por linea de comandos: sed '1s/^\xef\xbb\xbf//' input.json > output.json
  • Lectura en Python: usa encoding='utf-8-sig' para auto-eliminar
  • Node.js: usa fs.readFileSync(path, 'utf-8').replace(/^\ufeff/, '')

Al usar el Formateador JSON Piick, pegar JSON con BOM reporta “Unexpected token”, elimina manualmente el BOM o usa sed para pre-procesar.

Escenario real: Un companero en Windows escribe configuracion JSON → guarda → commit → CI ejecuta JSON.parse → falla. CI no elimina BOM automaticamente, hay que cambiar la configuracion del editor en la fuente. Agrega insert_final_newline = true y “encoding UTF-8 sin BOM” en .editorconfig, equipo unificado.

Error 6: Comillas Simples Tratadas como JSON

Sintoma: El dict de Python {'a': 1, 'b': 2} directamente pegado en el formateador JSON reporta error. La salida por defecto del dict de Python se parece a JSON, pero usa comillas simples, que no es JSON legal.

Por que: La especificacion JSON establece claramente las cadenas deben usar comillas dobles, las comillas simples no funcionan. El repr() del dict de Python produce comillas simples, la salida de cadena JSON produce comillas dobles:

Los nuevos facilmente tratan print(d) como JSON, lo pegan en la herramienta y reportan error.

Arreglo:

  • Al depurar Python, usa print(json.dumps(d, indent=2)) en vez de print(d)
  • La opcion “parseo tolerante” de la herramienta acepta comillas simples (Formateador JSON Piick soporta estilo JSON5)
  • Educa al equipo “Python dict != JSON, Python str usa comillas simples, JSON usa comillas dobles”

Escenario real: Un nuevo en Python depurando respuesta de API, print(response) produce {'code': 200, 'msg': 'ok'}, piensa que es JSON, lo copia a un companero del backend, el JSON.parse del companero falla. Primera trampa de depuracion del nuevo.

Error 7: Serializacion de NaN / Infinity / undefined

Sintoma: El objeto JS {a: NaN, b: Infinity, c: undefined} serializado con JSON.stringify se convierte en {"a":null,"b":null} (NaN e Infinity se vuelven null), los campos undefined desaparecen directamente. Si el backend usa un parser JSON estricto (por ejemplo, Python json.dumps luego json.loads), el comportamiento difiere: json.dumps de Python serializa float('nan') como NaN (no estandar), json.loads('NaN') reporta error.

Por que: La especificacion JSON no permite NaN / Infinity / undefined, pero JS es el lenguaje de uso diario para estos:

  • NaN / Infinity: son constantes globales de JS, producidas en errores de calculo numerico
  • undefined: bandera de JS “variable no definida”
  • JSON.stringify: los trata todos como null (undefined directamente descarta campos)
  • JSON.parse('NaN'): JS es permisivo, acepta como NaN (no estandar)
  • json.dumps(float('nan')): Python produce NaN (no estandar)
  • json.loads('NaN'): Python por defecto es estricto, reporta error

Al intercambiar datos entre lenguajes, el comportamiento de serializacion de NaN / Infinity / undefined es inconsistente, los bugs son faciles.

Arreglo:

  • Especificacion de API: nunca uses NaN / Infinity, usa null u omite para valores invalidos
  • Limpieza de datos: antes de serializar, manualmente if (x === undefined || Number.isNaN(x)) x = null
  • Validacion estricta del backend: Python json.dumps(..., allow_nan=False), fail-fast en error
  • Libreria: validacion JSON Schema en la entrada de la API, rechazar NaN / Infinity

Al usar el Formateador JSON Piick, pegar JSON con NaN / Infinity reporta “Unexpected token n” (porque NaN no es un token legal), reemplaza manualmente con null.

Escenario real: Frontend hace fetch a la API del backend, respuesta {score: NaN} (bug del backend), frontend JSON.parse obtiene score: NaN, consulta SQL WHERE score > 0 no devuelve filas (NaN > 0 es false), UI muestra “sin datos”, depurando medio dia para descubrir que es NaN. Nunca pases NaN, el backend hace validacion defensiva.

Error 8: Ordenar Claves Altera Git Diff / Semantica del Lenguaje

Sintoma: Activas la opcion “sort keys” de la herramienta, el JSON se ve ordenado, despues de git commit los companeros en la revision ven 100 lineas de diff, todos son cambios de orden de campos, sin cambio real de contenido. O mas grave: Go map / Python 3.7+ dict en algunos casos limite son sensibles al orden de claves, la semantica cambia despues de ordenar.

Por que: El objeto JSON es un mapa desordenado por definicion de la especificacion, pero RFC 8259 en realidad permite que las implementaciones preserven el orden (porque los literales de objeto JS, los dict de Python 3.7+ estan ordenados). La opcion sort keys de la herramienta es para mostrar orden, pero:

  1. Ruido en Git diff, afecta la calidad de la revision
  2. Protocolos JSON Canonicalization Scheme sensibles al orden de claves fallan
  3. El Object.keys(obj) de algunas librerias depende del orden de insercion, despues de ordenar el orden de forEach cambia

Arreglo: El JSON de produccion no ordena claves automaticamente. Durante el desarrollo usa la herramienta para ver la estructura, antes del commit usa jq o prettier para reformatear (preserva el orden original). Si el equipo realmente necesita un orden unificado, usa lint para forzar (sort-package-json para package.json), no confies en el ordenamiento en tiempo de ejecucion de la herramienta.

Al usar el Formateador JSON Piick, sort keys desactivado por defecto, solo activalo manualmente cuando “quiero ver la estructura”.

Escenario real: Un companero activa sort keys, hace commit de 1000 lineas de package.json todas reordenadas, el revisor mira el diff y ve 800 lineas son cambios de orden, 200 lineas son dependencias nuevas, 2 horas de revision desperdiciadas. No uses sort keys en configuracion de produccion.

Decisiones de Seleccion de Herramienta

Opcion A: Formateo Integrado en IDE (VSCode / WebStorm)

Mejor para: Escribir JSON a diario, ya usa un IDE.

Ventajas: Formateo en tiempo real, sin salir del editor, integra con schema (auto-completar claves). Inconvenientes: Solo JSON local, no se sincroniza entre herramientas (el formato del IDE difiere del formato de jq), sin procesamiento por lotes (auto-formato en CI requiere setup separado).

Opcion B: Herramientas de Linea de Comandos (jq / python -m json.tool)

Mejor para: Auto-formateo en CI / pipeline de build, proyectos con entorno shell.

Ventajas: Scriptable, en lote, combinado con lint, integracion CI. Inconvenientes: No intuitivo (salida de texto sin colores), sin resaltado de sintaxis, sin parseo tolerante (JSON5 / comillas simples / comentarios).

Opcion C: Formateador JSON Piick

Mejor para: Depuracion cross-herramienta (respuesta API + archivo de configuracion + payload JWT), no quiere paquete npm extra (proyecto puramente frontend), datos sensibles (configuracion API de produccion / JSON con PII) no quiere pasar por ningun servidor de terceros.

Ventajas: Cero dependencia (frontend puro JSON.parse + tokenizer), resaltado de sintaxis + ordenar claves + parseo tolerante (JSON5 / comillas simples / comentarios) + clic-para-saltar a posicion de error + 5 metricas (claves / arrays / profundidad maxima de anidamiento / bytes), datos locales. Inconvenientes: No se integra en CI (usa Opcion B para complementar), no puede auto-guardar (herramienta puramente frontend).

Arbol de decision:

  • Ya escribe JSON → Opcion A (plugin IDE)
  • Integracion CI + entorno shell → Opcion B (jq)
  • Depuracion cross-herramienta + datos sensibles + no instala nada → Opcion C (Piick)

5 Escenarios Reales

Escenario 1: Depuracion de Respuesta de API

Frontend llama a la API del backend, la respuesta es JSON minificado comprimido, pegas en la herramienta para auto-embellecer + plegar / expandir + + mostrar estadisticas (claves / arrays / profundidad).

Pasos:

  1. fetch API → response.text() → pegar en el Formateador JSON Piick
  2. Auto resaltado de sintaxis (5 tipos de token)
  3. Ver estadisticas arriba: {keys: 47, arrays: 12, maxDepth: 4, bytes: 1024}
  4. Clic-para-saltar a posicion de error: JSON.parse falla, clic en el banner de error, salta a la posicion del caracter que falla
  5. Copiar resultado formateado / plegar niveles de anidamiento

Sugerencia real: Siempre usa la herramienta para ver la respuesta de la API, no veas directamente JSON minificado en console.log, el ojo humano no puede leerlo.

Escenario 2: Validacion de package.json / Archivos de Configuracion

Al escribir package.json, typo (coma extra / falta corchete derecho / cadena sin cerrar), CI npm install falla, pero el editor no falla (IDE tolerante). Ejecuta validacion con herramienta.

Pasos:

  1. Copiar contenido de package.json → pegar en la herramienta
  2. La herramienta reporta error → ver “Line X, column Y” posicion de error → clic-para-saltar → arreglar
  3. Especialmente verificar: "scripts", "dependencies", "devDependencies" tres lugares (mas probable de typo)
  4. Antes del commit ejecuta npm install --dry-run para doble confirmacion

Sugerencia real: Usa la opcion “parseo tolerante” del Formateador JSON Piick (tolerant) para ver “error de sintaxis pero cerca de correcto” durante desarrollo, mas amigable que el parser estricto.

Escenario 3: Decodificacion de Payload JWT

JWT es JSON codificado en base64url, tres partes header.payload.signature. Al decodificar el payload para ver los claims, primero usa el Decodificador JWT Piick (mismo cluster doc) para dividir el base64, luego usa el Formateador JSON para verificar que el JSON decodificado sea legal.

Pasos:

  1. JWT eyJhbG...sw5c
  2. Decodificador JWT Piick divide tres partes
  3. el payload es {"sub":"1234567890","name":"John Doe","iat":1516239022} ← JSON minificado
  4. Pegar en el Formateador JSON Piick embellecer + ver campos de timestamp (iat / exp / nbf a tiempo legible)
  5. Verificar si exp ha expirado

Sugerencia real: Cadena de depuracion JWT: Decodificador JWT → Formateador JSON → Convertidor de Unix Timestamp (mismo cluster doc), conjunto de 3 piezas cubre el flujo completo.

Escenario 4: Serializacion de Snowflake ID / ID de Entero Grande

El backend usa int64 para devolver ID, el frontend hace fetch y id.toString() los ultimos bits se convierten en 0. Manejo de cadena.

Pasos:

  1. Backend Python json.dumps({"id": int(2**60)}) → salida {"id": 1152921504606846976} ← los ultimos bits pueden perder precision
  2. Arreglo: backend json.dumps({"id": str(2**60)}) → salida {"id": "1152921504606846976"} ← cadena, frontend maneja como cadena
  3. Frontend BigInt(id).toString() para operaciones matematicas
  4. UI muestra id.slice(0, 4) + "..." + id.slice(-4) (como visualizacion de numero de tarjeta bancaria)

Sugerencia real: Especificacion de API: IDs de enteros grandes siempre usan cadena. Frontend nunca asume que ID es Number.

Escenario 5: Archivos de Recursos i18n / Diccionarios Multilingues

Archivos JSON de i18n contienen chino / japones / emoji, maneja correctamente el escape Unicode. Desarrollo usa la herramienta para visualizacion, produccion usa UTF-8 + salida de formato legible ensure_ascii=False.

Pasos:

  1. Archivo i18n zh.json: {"hello":"你好,世界!🌏"} ← UTF-8 directo
  2. Pegar en el Formateador JSON Piick verifica que los caracteres UTF-8 se muestren normalmente
  3. Salida del backend usa json.dumps(..., ensure_ascii=False) (Python) o JSON.stringify (JS por defecto)
  4. Cabecera de respuesta: Content-Type: application/json; charset=utf-8
  5. CI agrega lint: eslint-plugin-unicorn o script personalizado verifica la configuracion ensure_ascii

Sugerencia real: Nunca escribas escape \uXXXX en cadenas JSON, durante el desarrollo escribe directamente caracteres legibles con UTF-8. Durante produccion deja que el framework / libreria decida como serializar, configura tu mismo ensure_ascii=False.

Practicas Recomendadas

  • Siempre valida JSON con herramienta (especialmente la configuracion de API de produccion), no confies en la tolerancia del IDE
  • Siempre parseo tolerante durante desarrollo (modo tolerante de la herramienta), produccion lint sin coma final + sin comentarios + sin comillas simples
  • IDs de enteros grandes siempre serializa como cadena (Snowflake ID / clave primaria distribuida), no asumas que el Number del frontend es seguro
  • No ordenes claves automaticamente (afecta Git diff y lenguajes sensibles al orden de claves), solo activalo manualmente cuando “veas estructura”
  • Unifica la indentacion (recomienda 2 espacios) + usa prettier / jq para auto-formateo, evita el formateo manual
  • Siempre usa UTF-8 + Content-Type charset=utf-8, no uses escape \uXXXX (legibilidad de desarrollo pobre)
  • CI ejecuta validacion JSON Schema, en la entrada de la API rechaza NaN / Infinity / falta de campos en modo estricto
  • Editor de Windows cierra BOM, .editorconfig equipo unificado, evita que el caracter BOM falle en CI
  • Usa el Formateador JSON Piick en linea para formatear / validar / embellecer, resaltado de sintaxis + parseo tolerante + clic-para-saltar a posicion de error + 5 metricas + datos locales sin envio. Combina con el Decodificador JWT Piick para dividir base64, Formateador SQL Piick para formatear SQL, Codificador/Decodificador URL Piick para manejar parametros URL, Generador de Cron Piick para generar expresiones cron, Probador de Regex Piick para probar regex de valores de campos JSON — conjunto de 5 piezas cubre todos los escenarios dev de JSON upstream / downstream

El formateo JSON no es embellecimiento, es infraestructura de legibilidad para API / configuracion / logs. El verdadero “formato correcto” = JSON estandar + UTF-8 + enteros grandes como cadenas + sin ordenar + sin coma final + equipo con indentacion unificada. Guarda en marcadores el Formateador JSON Piick — al depurar API / validar configuracion / parsear payload JWT, abrello, 1 minuto, eficiencia diaria de desarrollo +30%.