Casi todos los errores de JSON que vas a encontrar se reducen a una de nueve cosas. El mensaje del parser raremente dice cual es, porque la mayoria reportan el token en el que se atascaron en lugar del error cometido, y no son lo mismo. Aqui esta cada error, el mensaje que probablemente veas, y la correccion que lo resuelve.
Si quieres probarlo, pega cualquiera de estos ejemplos en el validador de JSON. Identifica el error y marca la linea.
1. Coma final
{
"name": "ana",
"role": "admin",
}
La coma despues de la ultima propiedad es valida en JavaScript y ilegal en JSON. La mayoria de parsers reportan esto en la llave de cierre, una linea debajo de la coma real, por eso la gente se queda mirando la llave sin encontrar nada mal.
Elimina la coma. Si te enfrentas a esto constantemente porque editas archivos de configuracion a mano, la herramienta de reparacion JSON las elimina y te muestra cada una que quito.
2. Comillas simples
{ 'name': 'ana' }
JSON tiene una sola sintaxis para cadenas y usa comillas dobles. Las comillas simples son un habito de JavaScript. La solucion es mecanica, y vale mas hacerla con una herramienta que a mano si el documento es grande, porque una comilla dentro de una cadena debe ser escapada en lugar de simplemente reemplazarse.
3. Claves sin comillas
{ name: "ana" }
Las claves de los objetos son cadenas, y las cadenas llevan comillas. Los literales de objetos en JavaScript permiten omitirlas, y de ahi viene este error siempre: alguien copio un objeto de un archivo fuente y esperaba que fuera JSON. No lo es.
4. Comentarios
{
// the account owner
"name": "ana"
}
JSON no permite comentarios. Douglas Crockford los elimino deliberadamente porque
la gente los usaba para incluir directivas de parsing. Tanto // como /* */ son
errores. Si los comentarios son importantes, guardalos en un archivo fuente y genera el JSON
a partir de el, o mueve la nota a un campo real como "_comment".
5. NaN, Infinity y undefined
{ "score": NaN, "limit": Infinity }
Ninguno de estos existe en JSON. No hay sintaxis para ellos en absoluto, por eso
el error normalmente aparece como una palabra suelta inesperada. Python escribe NaN y
Infinity cuando exportas flotantes sin cuidado, y JavaScript produce
undefined cuando falta una propiedad.
Tienes que decidir en que convertirlos, porque no hay una respuesta sin perdidas.
null es la opcion mas comun, una cadena como "NaN" es la otra. La
herramienta de reparacion elige null y enumera el cambio por separado de las
correcciones de puntuacion, porque este cambio modifica tus datos y no solo su formato.
6. Palabras clave con mayusculas incorrectas
{ "active": True, "deleted": NULL }
Las palabras clave de JSON en minusculas: true, false, null. True y None son
de Python, NULL es de SQL y C. Un parser que dice “unexpected token T” te esta diciendo
la verdad de la manera menos util posible.
7. Salto de linea dentro de una cadena
{ "note": "first line
second line" }
Una cadena de JSON no puede abarcar varias lineas. El salto de linea debe escribirse como \n
dentro de la cadena. Esto es comun cuando alguien pega texto multiliena en un
archivo de configuracion a mano, y el error resultante frecuentemente apunta a la siguiente linea, no a
la cadena que quedo abierta.
8. Numeros que JSON no permite
{ "a": .5, "b": +1, "c": 007, "d": 1_000 }
Cuatro reglas separadas. Un numero necesita un digito antes del punto decimal, asi que .5 es
0.5. No se permite un signo plus al inicio. No se permite un cero al inicio, lo cual
rechaza 007. Los separadores de digitos son una caracteristica del lenguaje, no de JSON.
9. Corchete sin cerrar
{
"user": {
"name": "ana"
}
El parser llega al final del archivo y reporta el error ahi, asi que el mensaje dice algo sobre la linea 200 de un documento de 200 lineas mientras la llave que falta esta en la linea 2. Este es el error para el que vale la pena tener una buena herramienta: el validador de este sitio reporta la posicion del corchete que se abrio y nunca se cerro, en lugar del final de la entrada.
Los dos errores que no son errores de sintaxis
Dos documentos pueden ser perfectamente validos y aun asi estar mal.
Una clave duplicada se analiza sin problemas. La especificacion lo permite, y cada parser que vayas a usar conserva el ultimo valor y descarta silenciosamente el anterior, de modo que los datos desaparecen sin ningun error en ningun lugar:
{ "region": "eu-west-1", "retries": 3, "region": "us-east-1" }
El validador reporta duplicados como advertencias con ambos numeros de linea, y aun asi considera el documento valido, porque eso es lo que la especificacion dice.
Un entero largo tambien se analiza sin problemas, y luego pierde precision en el momento en que algo lo lee como un double:
{ "id": 12345678901234567890 }
Leer eso con una libreria JSON tipica te da 1234567890123567000. Las
herramientas de este sitio trabajan en el flujo de tokens en lugar de parsearlo a un valor JavaScript, de modo que
el numero sobrevive al formateo, minificacion y comparacion sin cambiar. Por eso
la herramienta diff no dice que dos enteros de veinte digitos
son iguales solo porque colapsan al mismo valor de punto flotante.
Como leer un mensaje de error correctamente
Dos habitos ahorran la mayor parte del tiempo que la gente dedica a esto.
Primero, trata la posicion reportada como el punto donde el parser se rindio, no donde tu equivocaste. Una coma faltante se reporta en el siguiente token, un corchete sin cerrar al final del archivo, y una coma final en la llave de cierre.
Segundo, revisa el caracter antes de la posicion reportada. En la gran mayoria de casos el error real esta un token antes de la queja.
Si prefieres no hacer ninguna de las dos, pega el documento en el validador y lee el mensaje, que nombra el constructo equivocado en lugar de citar el token que no pudo parsearse.