Tutorial de JSON: sintaxis, reglas y cómo trabajar con JSON en JavaScript y Python

JSON es el formato de intercambio de datos más sencillo y más usado; con unas pocas reglas breves y dos funciones en cada lenguaje, puede leer, crear y guardar cualquier dato.

Pruébalo: Formateador de JSON

Si trabaja con APIs, apps móviles o incluso con el archivo de configuración de un proyecto, tarde o temprano se encontrará con JSON. JSON es un formato de texto para guardar y transportar datos que las personas pueden leer y que cualquier lenguaje de programación procesa con facilidad. Este tutorial empieza por la definición y las reglas de sintaxis, recorre un ejemplo real, pasa después a leer y escribir JSON en JavaScript y Python, con especial atención a las letras con tilde y a otros textos no ingleses, y termina con los errores comunes y cómo localizarlos con el formateador JSON. Todo el código de esta página se ha ejecutado, y las salidas son reales.

¿Qué es JSON?

JSON son las siglas de JavaScript Object Notation (notación de objetos de JavaScript). Su sintaxis procede de la forma en que se escriben los objetos en JavaScript, pero no está ligado a ningún lenguaje: Python, PHP, Java, C#, Go y prácticamente cualquier otro lenguaje tienen herramientas listas para trabajar con él. JSON está definido en los estándares RFC 8259 y ECMA-404, sus archivos usan la extensión .json y su tipo de medio en la web es application/json. Usos habituales:

  • APIs web: la mayoría de los servicios modernos envían sus peticiones y respuestas en JSON.
  • Archivos de configuración: como package.json en los proyectos de Node.js o composer.json en PHP.
  • Almacenamiento de datos: en el localStorage del navegador, en las columnas JSON de bases de datos como PostgreSQL y MySQL, y en las bases de datos documentales.

Reglas de sintaxis de JSON

Todo documento JSON se construye con seis tipos de valor, que pueden anidarse unos dentro de otros:

TipoEjemploDescripción
object (objeto){"city": "Lisbon"}Pares clave-valor entre llaves
array[1, 2, 3]Una lista ordenada de valores entre corchetes
string (cadena)"hello"Texto entre comillas dobles
number (número)42, -3.5, 1.2e6Entero o decimal, sin comillas
boolean (booleano)true, falseSolo en minúsculas
nullnullLa ausencia de valor

Las reglas que hay detrás de la mayoría de los errores:

  • Las claves son siempre cadenas entre comillas dobles: {"name": "Ali"} es correcto y {name: "Ali"} no lo es.
  • Solo se permiten comillas dobles; 'Ali' entre comillas simples no es JSON válido.
  • No se permiten comas finales: después del último miembro de un objeto o de un array no puede ir ninguna coma.
  • No hay comentarios: ni // ni /* */.
  • No se permiten valores propios de un lenguaje: undefined, NaN, Infinity, True y None no son JSON válido.
  • Los números no pueden empezar por cero: 012 no es válido. Por eso los números de teléfono, los códigos postales y otros identificadores parecidos deben escribirse como cadenas, por ejemplo "0123456789"; así también se conserva el cero inicial.
  • Los caracteres especiales dentro de las cadenas se escapan: \" para una comilla doble, \\ para una barra invertida, \n para un salto de línea y \uXXXX para cualquier carácter Unicode.
  • Los espacios y saltos de línea entre las partes no importan; por eso JSON puede escribirse tanto compacto en una sola línea como bien sangrado.

Un ejemplo real: un pedido de una tienda en línea

{
  "orderId": 10245,
  "createdAt": "2026-09-17T10:30:00Z",
  "customer": {
    "name": "Maria",
    "phone": "0123456789",
    "city": "Lisbon"
  },
  "items": [
    { "title": "Python for Beginners", "price": 32, "qty": 1 },
    { "title": "Wireless Mouse", "price": 45, "qty": 2 }
  ],
  "paid": true,
  "discountCode": null
}

Este ejemplo muestra todos los tipos de valor. customer (cliente) es un objeto anidado e items (artículos) es un array de objetos. Los precios son números, pero el teléfono es una cadena para que se conserve su cero inicial. JSON no tiene un tipo «fecha», así que la hora del pedido es una cadena en el formato estándar ISO 8601. Y discountCode usa null para indicar que este pedido no tenía código de descuento. Para leer el precio del segundo artículo, se escribe order.items[1].price en JavaScript y order["items"][1]["price"] en Python.

Trabajar con JSON en JavaScript

JavaScript tiene dos funciones integradas que bastan para la mayoría de las tareas: JSON.parse convierte un texto JSON en un objeto, y JSON.stringify convierte un objeto en texto JSON.

Leer JSON con JSON.parse

const text = '{"name": "Maria", "age": 28, "skills": ["JavaScript", "Python"], "active": true}';
const user = JSON.parse(text);

console.log(user.name);       // Maria
console.log(user.skills[0]);  // JavaScript
console.log(user.active);     // true

Crear JSON con JSON.stringify

const product = { title: "Café Guide", price: 32, tags: ["travel", "bestseller"], discount: null };

console.log(JSON.stringify(product));
console.log(JSON.stringify(product, null, 2));

La primera llamada produce JSON compacto en una sola línea, adecuado para enviarlo por la red, y la segunda, con 2 como tercer argumento, produce una salida legible sangrada con dos espacios. El segundo argumento sirve para filtrar o transformar valores y normalmente se deja en null. La salida:

{"title":"Café Guide","price":32,"tags":["travel","bestseller"],"discount":null}
{
  "title": "Café Guide",
  "price": 32,
  "tags": [
    "travel",
    "bestseller"
  ],
  "discount": null
}

Las letras con tilde y el resto del texto no ASCII se quedan exactamente como están en la salida de JSON.stringify; no se convierten en secuencias de escape \u.

Obtener JSON de una API y guardarlo en localStorage

async function loadProduct() {
  const res = await fetch("https://api.example.com/products/1");
  return await res.json();
}

localStorage.setItem("cart", JSON.stringify({ items: [101, 205] }));
const cart = JSON.parse(localStorage.getItem("cart"));
console.log(cart.items.length); // 2

El método res.json() ya analiza la respuesta y devuelve un objeto; no vuelva a pasar su resultado a JSON.parse. localStorage solo guarda cadenas, así que el objeto se convierte con JSON.stringify al guardarlo y con JSON.parse al leerlo.

Valores que JSON.stringify modifica

const data = { a: undefined, b: () => 1, c: NaN, d: new Date(Date.UTC(2026, 8, 17)) };
console.log(JSON.stringify(data));
// {"c":null,"d":"2026-09-17T00:00:00.000Z"}

Las claves cuyo valor es undefined o una función desaparecen sin avisar, NaN e Infinity se convierten en null, y una fecha se convierte en una cadena ISO. Al volver a analizar el resultado, la fecha sigue siendo una cadena y no vuelve a ser un Date por sí sola.

Gestionar errores

try {
  JSON.parse("{'name': 'Ali'}");
} catch (err) {
  console.log(err.name);    // SyntaxError
  console.log(err.message); // Expected property name or '}' in JSON at position 1 (line 1 column 2)
}

Cualquier texto no válido lanza un SyntaxError, así que procese dentro de try...catch los datos que llegan de fuera. El mensaje de arriba (que indica que se esperaba un nombre de propiedad o una llave de cierre) es la salida de Node.js, que coincide con la de Chrome; Firefox y Safari informan del mismo error con otras palabras.

Trabajar con JSON en Python

En Python, el módulo estándar json hace todo el trabajo y no hay que instalar nada. Tiene cuatro funciones principales: json.loads y json.dumps trabajan con cadenas, mientras que json.load y json.dump trabajan directamente con archivos; la s de las dos primeras viene de string (cadena).

Convertir una cadena JSON en un diccionario

import json

text = '{"name": "Maria", "age": 28, "skills": ["JavaScript", "Python"], "active": true}'
user = json.loads(text)

print(user["name"])     # Maria
print(type(user))       # <class 'dict'>
print(user["active"])   # True
JSONPythonJavaScript
objectdictObject
arraylistArray
stringstrString
numberint o floatNumber
true / falseTrue / Falsetrue / false
nullNonenull

Convertir datos a JSON y el problema del texto no ASCII

product = {"title": "Café Guide", "price": 32, "tags": ["travel", "bestseller"], "discount": None}

print(json.dumps(product))
print(json.dumps(product, ensure_ascii=False, indent=2))

La primera línea de la salida puede sorprenderle:

{"title": "Caf\u00e9 Guide", "price": 32, "tags": ["travel", "bestseller"], "discount": null}

Por defecto, json.dumps escribe cada carácter no ASCII con la forma \uXXXX, así que é pasa a ser \u00e9, y el texto en cualquier otra escritura se escapa carácter a carácter de la misma manera. Una palabra como «año» o «canción» sale igual de ilegible. Esta salida es válida y cualquier programa la lee correctamente, pero las personas no pueden leerla y ocupa más espacio. Con ensure_ascii=False el texto se escribe exactamente como es, e indent=2 organiza la salida igual que en el ejemplo de JavaScript.

Leer y escribir archivos JSON

with open("product.json", "w", encoding="utf-8") as f:
    json.dump(product, f, ensure_ascii=False, indent=2)

with open("product.json", encoding="utf-8") as f:
    loaded = json.load(f)

print(loaded["tags"][0])   # travel

Dos puntos importantes: pase también ensure_ascii=False a json.dump, y abra siempre el archivo con encoding="utf-8". En Windows, si no indica la codificación, Python puede recurrir a la codificación predeterminada del sistema, que no es UTF-8; el resultado es un UnicodeEncodeError o un archivo lleno de caracteres extraños.

La salida de print no es JSON

print(product)
# {'title': 'Café Guide', 'price': 32, 'tags': ['travel', 'bestseller'], 'discount': None}

Un error muy habitual es pegar en algún sitio, como si fuera JSON, la salida de print de un diccionario. Ese texto es la representación propia de Python de los datos: lleva comillas simples y None en lugar de null, así que ningún analizador JSON lo aceptará. Para crear JSON, use siempre json.dumps.

Gestionar errores en Python

try:
    json.loads("{'name': 'Ali'}")
except json.JSONDecodeError as e:
    print(e)  # Expecting property name enclosed in double quotes: line 1 column 2 (char 1)

json.JSONDecodeError es una subclase de ValueError, y sus atributos lineno, colno y pos indican la posición del error. Si usa la biblioteca requests, response.json() hace la misma conversión con la respuesta de una API. Una diferencia sutil: por defecto, Python acepta NaN en la entrada y también lo escribe en la salida, aunque ese valor no es JSON estándar; para impedirlo, pase allow_nan=False a json.dumps.

Errores comunes de JSON y qué significan los mensajes

Los mensajes de error se muestran tal como los imprimen Node.js, Chrome y Python, en inglés:

ErrorEjemplo no válidoMensaje de JavaScript (Node.js y Chrome)Mensaje de Python
Comillas simples o clave sin comillas{'name': 'Ali'}Expected property name or '}'Expecting property name enclosed in double quotes
Coma final en un objeto{"a": 1,}Expected double-quoted property namePython 3.14: Illegal trailing comma before end of object; Python 3.12: Expecting property name enclosed in double quotes
Coma final en un array[1, 2,]Unexpected token ']'Python 3.14: Illegal trailing comma before end of array; Python 3.12: Expecting value
Falta una coma, o hay un comentario tras un valor{"a": 1 "b": 2}Expected ',' or '}' after property valueExpecting ',' delimiter
Un valor de Python o de JavaScript{"a": True}Unexpected token 'T'Expecting value
Un número con cero inicial{"phone": 0123456789}Unexpected numberExpecting ',' delimiter
Cadena sin cerrar{"a": "x}Unterminated stringUnterminated string starting at
Entrada vacíaTexto vacíoUnexpected end of JSON inputExpecting value

Los mensajes suelen indicar también la posición, como position 8 o line 1 column 9, y el problema real suele estar justo antes de ese punto. Si un mensaje de JavaScript empieza por Unexpected token '<', probablemente ha recibido una página HTML en lugar de JSON, por ejemplo una página de error 404 o una de inicio de sesión; la guía sobre el error Unexpected token analiza ese caso. Un archivo guardado con BOM produce en Python el error Unexpected UTF-8 BOM; ábralo con encoding="utf-8-sig" o guárdelo sin BOM.

Formatear y validar con el formateador JSON

Cuando un documento JSON largo llega en una sola línea, o no consigue averiguar por qué no se analiza, el formateador JSON es la forma más rápida de avanzar. La herramienta usa el propio analizador JSON del navegador y los datos nunca salen de su navegador, así que puede inspeccionar sin riesgo respuestas de API que contienen tokens o datos de usuarios. Los pasos:

  1. Pegue el JSON en el cuadro JSON de entrada; se formatea al instante, y el botón Formatear hace lo mismo.
  2. Elija la sangría en el menú Sangría: 2 espacios, 4 espacios o Tabulación.
  3. Si el JSON no es válido, un mensaje que empieza por JSON no válido: muestra el texto de error del navegador, que normalmente incluye la posición del problema; use la tabla anterior para entender qué significa y corregirlo.
  4. La pestaña Árbol muestra los datos como un árbol plegable, y Expandir todo y Contraer todo abren o cierran todas las ramas; muy práctico para encontrar una clave en una respuesta grande.
  5. Para enviar o guardar los datos de forma compacta, Minificar elimina todos los espacios y saltos de línea. Copie el resultado con Copiar.

Cuando su código necesite tipos para el JSON que recibe, JSON a tipos genera definiciones de TypeScript, Go o Python a partir de una muestra; la guía sobre cómo tipar la respuesta de una API en TypeScript explica el proceso paso a paso.

Preguntas Frecuentes

¿Qué es JSON y en qué se diferencia de un objeto de JavaScript?

JSON es un formato de texto para guardar e intercambiar datos cuya sintaxis procede de los objetos de JavaScript, pero es más estricto: las claves deben ir entre comillas dobles, no se permiten comentarios ni comas finales, y valores como undefined y las funciones no existen en él.

¿Por qué Python escribe é como \u00e9 en JSON?

Porque json.dumps usa ensure_ascii=True por defecto y escapa todos los caracteres no ASCII. La salida es válida, pero para una salida legible pase ensure_ascii=False y escriba el archivo con encoding="utf-8".

¿Se pueden escribir comentarios en un archivo JSON?

No. El JSON estándar no tiene comentarios, y JSON.parse y json.loads lanzan un error cuando encuentran uno. Algunas herramientas, como la configuración de VS Code, aceptan un formato ampliado con comentarios, pero eso no es JSON estándar.

¿Qué diferencia hay entre json.loads y json.load en Python?

json.loads convierte una cadena JSON en datos de Python, y json.load lee directamente de un archivo abierto. Del mismo modo, json.dumps devuelve una cadena y json.dump escribe los datos en un archivo.
Pruébalo: Formateador de JSON