El idioma común de las aplicaciones modernas
Cada vez que una aplicación móvil carga tu perfil, una web muestra el tiempo de tu ciudad o un servicio envía una notificación a otro, hay datos viajando de un sistema a otro. Para que esos sistemas se entiendan, aunque estén escritos en lenguajes distintos y funcionen en máquinas diferentes, necesitan un formato común. Hoy, ese formato es casi siempre JSON.
JSON, siglas de JavaScript Object Notation, es un formato de texto para representar datos estructurados. Nació a principios de los años 2000 como alternativa más ligera a XML, que entonces dominaba el intercambio de datos, y se impuso rápidamente gracias a su sencillez: es fácil de leer para las personas, fácil de generar y analizar para las máquinas, y está soportado por prácticamente todos los lenguajes de programación.
Hoy JSON está en todas partes: en las respuestas de las APIs REST, en los archivos de configuración como package.json o tsconfig.json, en bases de datos documentales como MongoDB, en columnas de PostgreSQL, en los registros de logs estructurados y en las llamadas a herramientas de los modelos de lenguaje.
En esta guía veremos su sintaxis y sus tipos de datos, cómo construir documentos reales, en qué se diferencia de un objeto de JavaScript, cómo convertirlo en distintos lenguajes, cómo validarlo con JSON Schema y cómo resolver los errores más frecuentes.
La sintaxis de JSON en pocas reglas
La sintaxis de JSON es deliberadamente pequeña. Un documento JSON se construye con unas pocas reglas:
- Los datos se organizan en pares clave-valor.
- Las claves son siempre cadenas entre comillas dobles.
- La clave y el valor se separan con dos puntos.
- Los pares se separan con comas, sin coma después del último.
- Los objetos se delimitan con llaves
{}y los arrays con corchetes[]. - No se permiten comentarios.
Un primer ejemplo, la ficha de un libro:
{
"titulo": "Cien años de soledad",
"autor": "Gabriel García Márquez",
"anio": 1967,
"disponible": true
}
El nivel superior de un documento suele ser un objeto o un array. La especificación actual, recogida en el RFC 8259 y en el estándar ECMA-404, permite también que el documento sea un valor suelto, como un número o una cadena, aunque en la práctica casi siempre se usa un objeto o un array.
Los archivos JSON usan la extensión .json, deben codificarse en UTF-8 y se sirven en HTTP con el tipo de contenido application/json.
Los tipos de datos
JSON admite seis tipos de valores, ni uno más:
{
"cadena": "Hola, mundo",
"numero_entero": 42,
"numero_decimal": 3.14,
"numero_exponente": 6.02e23,
"booleano": false,
"nulo": null,
"array": [1, "dos", true, null],
"objeto": { "anidado": "sí" }
}
Las cadenas usan siempre comillas dobles; las simples no son válidas. Admiten secuencias de escape como \n para el salto de línea, \" para las comillas, \\ para la barra invertida y \u00F1 para caracteres Unicode.
Los números se escriben en base decimal, con o sin parte fraccionaria y exponente. No se admiten ceros a la izquierda, como 007, ni prefijos como 0x, ni los valores especiales NaN o Infinity.
Los booleanos son true y false, en minúsculas, y el valor nulo es null.
Lo que no existe en JSON es igual de importante: no hay fechas, ni undefined, ni funciones, ni tipos binarios. Las fechas se representan habitualmente como cadenas en formato ISO 8601, como "2026-10-17T14:30:00Z", y los datos binarios, codificados en Base64.
Un documento real: una ficha de empleado
Veamos un ejemplo más completo que combina todos los tipos. Este archivo, empleado.json, describe a una persona de una empresa:
{
"id": "EMP-0419",
"nombre": "Lucía Fernández",
"puestos": ["desarrolladora backend", "mentora"],
"edad": 34,
"fecha_alta": "2021-03-15",
"teletrabajo": true,
"direccion": {
"calle": "Calle Mayor 12",
"ciudad": "Zaragoza",
"codigo_postal": "50001",
"pais": "España"
},
"recomendado_por": null
}
Hay varias decisiones de modelado interesantes. Los puestos son un array porque una persona puede tener varios. La dirección es un objeto anidado que agrupa sus campos relacionados. La fecha de alta es una cadena en formato ISO. El código postal es una cadena y no un número, porque podría empezar por cero y no se usa para hacer cálculos. Y recomendado_por vale null para indicar explícitamente que no hay recomendación, en lugar de omitir el campo.
Para representar varios empleados se usa un array de objetos:
[
{
"id": "EMP-0419",
"nombre": "Lucía Fernández",
"recomendado_por": null
},
{
"id": "EMP-0420",
"nombre": "Marcos Ortega",
"recomendado_por": "EMP-0419"
}
]
En las APIs es habitual envolver ese array en un objeto, para poder añadir metadatos como la paginación sin romper la estructura:
{
"datos": [{ "id": "EMP-0419", "nombre": "Lucía Fernández" }],
"pagina": 1,
"total": 87
}
JSON frente a objetos de JavaScript
La sintaxis de JSON se inspiró en la notación de objetos literales de JavaScript, y por eso se parecen tanto. Pero no son lo mismo, y confundirlos es un error frecuente.
Un objeto de JavaScript es una estructura en memoria que existe mientras se ejecuta el programa. JSON es texto, una cadena de caracteres que se puede guardar en un archivo o enviar por la red. Además, un objeto literal de JavaScript admite cosas que JSON no permite:
const usuario = {
nombre: "Ana", // clave sin comillas y comillas simples
edad: 31,
saludar() {
// métodos
return `Hola, soy ${this.nombre}`;
},
ultimoAcceso: undefined, // undefined
// comentarios
};
Nada de eso es válido en JSON. Además, JSON es independiente del lenguaje: Python, Java, Go, PHP, C#, Rust o Swift lo leen y lo escriben con la misma facilidad. Por eso es el formato elegido para que sistemas heterogéneos se comuniquen.
Como JSON es texto, en JavaScript se puede guardar en una variable de tipo cadena, incluso con plantillas que insertan valores:
const edad = 31;
const textoJson = `{
"nombre": "Ana",
"edad": ${edad}
}`;
Construir JSON a mano con plantillas es frágil, porque cualquier comilla o carácter especial en los valores romperá el documento. Para generarlo, la forma correcta es usar JSON.stringify.
Convertir entre JSON y JavaScript
JavaScript incluye un objeto global llamado JSON con dos métodos fundamentales para pasar de un mundo al otro. Conviene no confundir este objeto, que es una utilidad del lenguaje, con el formato JSON en sí. Dominar JSON.parse y JSON.stringify es imprescindible en cualquier proyecto web.
JSON.parse convierte una cadena JSON en un valor de JavaScript:
const respuesta = '{"producto":"Teclado","precio":49.9,"stock":12}';
const producto = JSON.parse(respuesta);
console.log(producto.precio * 2);
99.8
JSON.stringify hace lo contrario, convirtiendo un valor en una cadena JSON:
const pedido = { id: 1042, total: 58.4, articulos: ["café", "taza"] };
console.log(JSON.stringify(pedido));
{"id":1042,"total":58.4,"articulos":["café","taza"]}
El tercer argumento de JSON.stringify indica la indentación, útil para mostrar el resultado de forma legible o guardarlo en archivos:
console.log(JSON.stringify({ a: 1, b: [1, 2] }, null, 2));
{
"a": 1,
"b": [
1,
2
]
}
El segundo argumento permite filtrar propiedades. Si es un array, solo se incluyen las claves indicadas, algo útil para no exponer datos sensibles:
const usuario = { id: 1, nombre: "Ana", contrasena: "secreta" };
console.log(JSON.stringify(usuario, ["id", "nombre"]));
{"id":1,"nombre":"Ana"}
Lo que se pierde al serializar
JSON.stringify no puede representar todos los valores de JavaScript, y es importante saber qué ocurre con cada uno para evitar sorpresas:
const datos = {
nombre: "Ana",
saludar: () => "hola",
apodo: undefined,
alta: new Date(Date.UTC(2026, 9, 17)),
puntuacion: NaN,
};
console.log(JSON.stringify(datos));
{"nombre":"Ana","alta":"2026-10-17T00:00:00.000Z","puntuacion":null}
Las funciones y los valores undefined desaparecen; las fechas se convierten en cadenas ISO; y NaN e Infinity se convierten en null. Los Map y Set se serializan como objetos vacíos, y los BigInt provocan un error:
TypeError: Do not know how to serialize a BigInt
Las referencias circulares, un objeto que se contiene a sí mismo, también lanzan una excepción:
TypeError: Converting circular structure to JSON
Al volver a leer el JSON con JSON.parse, las fechas siguen siendo cadenas. Para reconstruirlas se usa el segundo argumento de parse, una función reviver que transforma cada valor:
const texto = '{"fecha":"2026-10-17T00:00:00.000Z"}';
const objeto = JSON.parse(texto, (clave, valor) =>
clave === "fecha" ? new Date(valor) : valor
);
console.log(objeto.fecha instanceof Date);
true
Un uso antiguo de JSON.parse(JSON.stringify(obj)) era clonar objetos en profundidad. Hoy existe structuredClone, disponible en navegadores y en Node.js, que conserva fechas, Map, Set y referencias circulares.
Otra limitación menos conocida afecta a los números grandes. JavaScript solo representa enteros con exactitud hasta 2^53 - 1, así que los identificadores de 64 bits pierden precisión al analizarse:
console.log(JSON.parse("12345678901234567890"));
12345678901234567000
Por eso muchas APIs, como la de X o la de Discord, envían los identificadores grandes como cadenas.
JSON en otros lenguajes
En Python, el módulo json de la biblioteca estándar ofrece loads y dumps para cadenas, y load y dump para archivos:
import json
empleado = {"nombre": "Lucía", "teletrabajo": True, "recomendado_por": None,
"ciudad": "Bogotá"}
texto = json.dumps(empleado, ensure_ascii=False)
print(texto)
with open("empleado.json", "w", encoding="utf-8") as archivo:
json.dump(empleado, archivo, ensure_ascii=False, indent=2)
with open("empleado.json", encoding="utf-8") as archivo:
datos = json.load(archivo)
{"nombre": "Lucía", "teletrabajo": true, "recomendado_por": null, "ciudad": "Bogotá"}
Python convierte True, False y None en true, false y null automáticamente. La opción ensure_ascii=False mantiene los caracteres acentuados en lugar de escaparlos como \u00e1.
En Go, los structs se mapean a JSON mediante etiquetas:
type Empleado struct {
ID string `json:"id"`
Nombre string `json:"nombre"`
RecomendadoPor *string `json:"recomendado_por"`
}
var e Empleado
err := json.Unmarshal(datos, &e)
Y en Java, librerías como Jackson o Gson cumplen la misma función, convirtiendo objetos en JSON y viceversa.
JSON en las APIs web
El uso más común de JSON es el intercambio de datos entre un cliente y un servidor a través de una API. Con fetch, recibir y enviar JSON es directo:
const respuesta = await fetch("https://api.tienda.example/productos/42");
if (!respuesta.ok) throw new Error(`HTTP ${respuesta.status}`);
const producto = await respuesta.json();
await fetch("https://api.tienda.example/pedidos", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ productoId: 42, cantidad: 2 }),
});
El método respuesta.json() lee el cuerpo y lo analiza con JSON.parse. Al enviar datos, hay que serializarlos con JSON.stringify e indicar la cabecera Content-Type: application/json, para que el servidor sepa cómo interpretar el cuerpo.
En el lado del servidor, los frameworks modernos hacen esto de forma transparente. En Express, por ejemplo, el middleware express.json() analiza los cuerpos entrantes, y res.json() serializa las respuestas.
Validar JSON con JSON Schema
Que un documento sea JSON válido no significa que tenga la estructura que tu aplicación espera. Un pedido puede llegar sin el campo cantidad, o con un precio negativo, y seguir siendo JSON perfectamente correcto.
El formato JSON Schema es un estándar para describir la estructura que debe tener un documento: qué campos son obligatorios, de qué tipo es cada uno y qué restricciones cumplen. El propio esquema se escribe en JSON:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["productoId", "cantidad"],
"properties": {
"productoId": { "type": "integer", "minimum": 1 },
"cantidad": { "type": "integer", "minimum": 1, "maximum": 99 },
"nota": { "type": "string", "maxLength": 200 }
},
"additionalProperties": false
}
Hay validadores para todos los lenguajes, como Ajv en JavaScript o jsonschema en Python. Validar en el servidor todo el JSON que llega desde fuera es una práctica de seguridad básica. En el ecosistema de TypeScript, librerías como Zod o Valibot cumplen una función similar y además infieren los tipos.
JSON Schema se usa también en especificaciones como OpenAPI, para documentar APIs, y en las salidas estructuradas de los modelos de lenguaje, donde el esquema garantiza que la respuesta del modelo tenga el formato esperado.
Herramientas para trabajar con JSON
Algunas herramientas facilitan mucho el trabajo diario con este formato.
jq es una utilidad de línea de comandos para consultar y transformar JSON, imprescindible para trabajar con APIs desde la terminal:
curl -s https://api.tienda.example/empleados \
| jq '.usuarios[] | select(.edad > 30) | .nombre'
"Ana"
Los editores como Visual Studio Code validan la sintaxis mientras escribes, formatean el documento y, si el archivo declara un esquema, ofrecen autocompletado. Los navegadores muestran las respuestas JSON con un visor integrado. Y Python incluye un formateador desde la terminal:
python -m json.tool empleado.json
Variantes y alternativas
La ausencia de comentarios y la rigidez de la sintaxis hacen que JSON sea incómodo para archivos de configuración escritos a mano. Por eso han surgido variantes. JSONC, JSON con comentarios, es el que usan VS Code y TypeScript en tsconfig.json. JSON5 añade comillas simples, claves sin comillas y comas finales. Ninguno es JSON estándar, así que no deben usarse para intercambiar datos entre sistemas.
Para procesar grandes volúmenes existe JSON Lines, o NDJSON, que guarda un documento JSON por línea. Permite leer los datos de forma secuencial sin cargar todo el archivo en memoria, y es habitual en logs y exportaciones de datos.
Frente a otros formatos, YAML es más legible para configuraciones y admite comentarios, pero su sintaxis basada en la indentación es más propensa a errores. XML sigue presente en sistemas empresariales y documentos, pero es mucho más verboso. Y formatos binarios como Protocol Buffers o MessagePack son más compactos y rápidos, a cambio de no ser legibles por personas.
JSON en las bases de datos
JSON no solo viaja entre aplicaciones: también se almacena. Las bases de datos documentales, como MongoDB o CouchDB, guardan cada registro como un documento con estructura similar a JSON, lo que permite que cada uno tenga campos distintos sin modificar un esquema global.
Las bases de datos relacionales también lo han incorporado. PostgreSQL ofrece el tipo jsonb, que almacena el documento en un formato binario indexable y permite consultar su contenido con operadores específicos:
CREATE TABLE eventos (
id serial PRIMARY KEY,
datos jsonb NOT NULL
);
INSERT INTO eventos (datos)
VALUES ('{"tipo": "compra", "usuario": 87, "importe": 58.4}');
SELECT datos->>'tipo' AS tipo, (datos->>'importe')::numeric AS importe
FROM eventos
WHERE datos @> '{"tipo": "compra"}';
El operador ->> extrae un campo como texto y @> comprueba si el documento contiene otro. Con un índice GIN sobre la columna, estas consultas son eficientes incluso con millones de filas. MySQL, SQLite y SQL Server ofrecen funciones equivalentes.
Guardar JSON en una base de datos relacional es útil para datos con estructura variable, como metadatos, preferencias de usuario o eventos de terceros. Para los datos centrales de la aplicación, que se consultan y relacionan con frecuencia, las columnas tradicionales siguen siendo la mejor opción.
Buenas prácticas al diseñar documentos JSON
Algunas convenciones hacen que los documentos sean más claros y fáciles de mantener:
- Elige un estilo para las claves y mantenlo en toda la API:
camelCasees habitual en JavaScript ysnake_caseen Python o Ruby. - Usa el formato ISO 8601 con zona horaria para las fechas.
- Representa los identificadores largos y los importes monetarios exactos como cadenas o como enteros en céntimos, para evitar problemas de precisión.
- Distingue entre un campo ausente y un campo con valor
null, y documenta qué significa cada caso. - Evita anidar demasiados niveles; las estructuras planas son más fáciles de consultar y validar.
- Versiona tu API cuando cambies la estructura de forma incompatible.
- No incluyas nunca contraseñas, tokens ni datos personales innecesarios en las respuestas.
Errores comunes y cómo resolverlos
Los errores de análisis de JSON son de los más frecuentes en desarrollo web. Los mensajes de las versiones actuales de Node.js y de los navegadores basados en Chromium son bastante descriptivos.
Claves sin comillas o con comillas simples:
JSON.parse('{nombre: "Ana"}');
SyntaxError: Expected property name or '}' in JSON at position 1 (line 1 column 2)
Una coma después del último elemento:
JSON.parse('{"a": 1,}');
SyntaxError: Expected double-quoted property name in JSON at position 7 (line 1 column 8)
Analizar algo que no es una cadena JSON, como undefined, normalmente porque una variable no se inicializó o una respuesta llegó vacía:
SyntaxError: "undefined" is not valid JSON
Y uno de los más habituales al trabajar con APIs: recibir HTML en lugar de JSON, porque el servidor devolvió una página de error. El mensaje indica que el primer carácter es <:
SyntaxError: Unexpected token '<', "<!DOCTYPE html>" is not valid JSON
Comprueba siempre respuesta.ok y la cabecera Content-Type antes de llamar a respuesta.json(), y revisa en la pestaña de red de las herramientas del navegador qué devolvió realmente el servidor.
En Python, el equivalente es json.JSONDecodeError:
json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
Por último, envuelve siempre en un bloque try el análisis de JSON que proceda de fuentes externas, para que un documento mal formado no detenga tu aplicación:
function analizarSeguro(texto, porDefecto = null) {
try {
return JSON.parse(texto);
} catch {
return porDefecto;
}
}
Conclusiones
JSON es un formato de texto sencillo para representar datos estructurados mediante pares clave-valor, objetos y arrays. Su sintaxis se reduce a unas pocas reglas, comillas dobles obligatorias, sin comas finales y sin comentarios, y admite solo seis tipos de valores: cadenas, números, booleanos, null, arrays y objetos.
Aunque nació a partir de la notación de objetos de JavaScript, JSON es texto e independiente del lenguaje, lo que lo ha convertido en el estándar para el intercambio de datos en APIs, configuraciones, bases de datos y logs. En JavaScript, JSON.parse y JSON.stringify convierten entre el texto y los valores del lenguaje, con matices importantes: las fechas se transforman en cadenas, las funciones y undefined desaparecen, y los números muy grandes pierden precisión.
Para trabajar con JSON de forma robusta conviene validar la estructura con JSON Schema o con librerías equivalentes, manejar los errores de análisis con try, comprobar las respuestas de las APIs antes de analizarlas y apoyarse en herramientas como jq y los validadores de los editores.
Con estos fundamentos, podrás diseñar documentos JSON claros, consumir y crear APIs con confianza y diagnosticar en segundos los errores que antes parecían misteriosos.
````markdown
---
title: "Qué es JSON: sintaxis, ejemplos y cómo usarlo en tus proyectos"
description: "Aprende qué es JSON, su sintaxis y tipos de datos, cómo usar JSON.parse y JSON.stringify, validarlo con JSON Schema y evitar errores comunes."
slug: "que-es-json-sintaxis-ejemplos-y-como-usarlo-en-tus-proyectos"
weight: 0
header: true
type: "post"
draft: false
tags:
- "que es json formato"
- "json parse y stringify"
- "json vs objeto javascript"
- "tipos de datos json"
- "archivo json ejemplo"
- "json schema validacion"
- "json en python"
- "jq terminal"
- "api rest"
- "json"
categories:
- "lenguajes"
- "backend"
date: "2026-10-17 14:17:23"
---
## El idioma común de las aplicaciones modernas
Cada vez que una aplicación móvil carga tu perfil, una web muestra el tiempo de tu ciudad o un servicio envía una notificación a otro, hay datos viajando de un sistema a otro. Para que esos sistemas se entiendan, aunque estén escritos en lenguajes distintos y funcionen en máquinas diferentes, necesitan un formato común. Hoy, ese formato es casi siempre JSON.
JSON, siglas de JavaScript Object Notation, es un formato de texto para representar datos estructurados. Nació a principios de los años 2000 como alternativa más ligera a XML, que entonces dominaba el intercambio de datos, y se impuso rápidamente gracias a su sencillez: es fácil de leer para las personas, fácil de generar y analizar para las máquinas, y está soportado por prácticamente todos los lenguajes de programación.
Hoy JSON está en todas partes: en las respuestas de las APIs REST, en los archivos de configuración como `package.json` o `tsconfig.json`, en bases de datos documentales como MongoDB, en columnas de PostgreSQL, en los registros de logs estructurados y en las llamadas a herramientas de los modelos de lenguaje.
En esta guía veremos su sintaxis y sus tipos de datos, cómo construir documentos reales, en qué se diferencia de un objeto de JavaScript, cómo convertirlo en distintos lenguajes, cómo validarlo con JSON Schema y cómo resolver los errores más frecuentes.
## La sintaxis de JSON en pocas reglas
La **sintaxis de JSON** es deliberadamente pequeña. Un documento JSON se construye con unas pocas reglas:
- Los datos se organizan en pares clave-valor.
- Las claves son siempre cadenas entre comillas dobles.
- La clave y el valor se separan con dos puntos.
- Los pares se separan con comas, sin coma después del último.
- Los objetos se delimitan con llaves `{}` y los arrays con corchetes `[]`.
- No se permiten comentarios.
Un primer ejemplo, la ficha de un libro:
```json
{
"titulo": "Cien años de soledad",
"autor": "Gabriel García Márquez",
"anio": 1967,
"disponible": true
}
```
El nivel superior de un documento suele ser un objeto o un array. La especificación actual, recogida en el RFC 8259 y en el estándar ECMA-404, permite también que el documento sea un valor suelto, como un número o una cadena, aunque en la práctica casi siempre se usa un objeto o un array.
Los archivos JSON usan la extensión `.json`, deben codificarse en UTF-8 y se sirven en HTTP con el tipo de contenido `application/json`.
## Los tipos de datos
JSON admite seis tipos de valores, ni uno más:
```json
{
"cadena": "Hola, mundo",
"numero_entero": 42,
"numero_decimal": 3.14,
"numero_exponente": 6.02e23,
"booleano": false,
"nulo": null,
"array": [1, "dos", true, null],
"objeto": { "anidado": "sí" }
}
```
Las cadenas usan siempre comillas dobles; las simples no son válidas. Admiten secuencias de escape como `\n` para el salto de línea, `\"` para las comillas, `\\` para la barra invertida y `\u00F1` para caracteres Unicode.
Los números se escriben en base decimal, con o sin parte fraccionaria y exponente. No se admiten ceros a la izquierda, como `007`, ni prefijos como `0x`, ni los valores especiales `NaN` o `Infinity`.
Los booleanos son `true` y `false`, en minúsculas, y el valor nulo es `null`.
Lo que no existe en JSON es igual de importante: no hay fechas, ni `undefined`, ni funciones, ni tipos binarios. Las fechas se representan habitualmente como cadenas en formato ISO 8601, como `"2026-10-17T14:30:00Z"`, y los datos binarios, codificados en Base64.
## Un documento real: una ficha de empleado
Veamos un ejemplo más completo que combina todos los tipos. Este archivo, `empleado.json`, describe a una persona de una empresa:
```json
{
"id": "EMP-0419",
"nombre": "Lucía Fernández",
"puestos": ["desarrolladora backend", "mentora"],
"edad": 34,
"fecha_alta": "2021-03-15",
"teletrabajo": true,
"direccion": {
"calle": "Calle Mayor 12",
"ciudad": "Zaragoza",
"codigo_postal": "50001",
"pais": "España"
},
"recomendado_por": null
}
```
Hay varias decisiones de modelado interesantes. Los puestos son un array porque una persona puede tener varios. La dirección es un objeto anidado que agrupa sus campos relacionados. La fecha de alta es una cadena en formato ISO. El código postal es una cadena y no un número, porque podría empezar por cero y no se usa para hacer cálculos. Y `recomendado_por` vale `null` para indicar explícitamente que no hay recomendación, en lugar de omitir el campo.
Para representar varios empleados se usa un array de objetos:
```json
[
{
"id": "EMP-0419",
"nombre": "Lucía Fernández",
"recomendado_por": null
},
{
"id": "EMP-0420",
"nombre": "Marcos Ortega",
"recomendado_por": "EMP-0419"
}
]
```
En las APIs es habitual envolver ese array en un objeto, para poder añadir metadatos como la paginación sin romper la estructura:
```json
{
"datos": [
{ "id": "EMP-0419", "nombre": "Lucía Fernández" }
],
"pagina": 1,
"total": 87
}
```
## JSON frente a objetos de JavaScript
La sintaxis de JSON se inspiró en la notación de objetos literales de JavaScript, y por eso se parecen tanto. Pero no son lo mismo, y confundirlos es un error frecuente.
Un objeto de JavaScript es una estructura en memoria que existe mientras se ejecuta el programa. JSON es texto, una cadena de caracteres que se puede guardar en un archivo o enviar por la red. Además, un objeto literal de JavaScript admite cosas que JSON no permite:
```javascript
const usuario = {
nombre: 'Ana', // clave sin comillas y comillas simples
edad: 31,
saludar() { // métodos
return `Hola, soy ${this.nombre}`;
},
ultimoAcceso: undefined, // undefined
// comentarios
};
```
Nada de eso es válido en JSON. Además, JSON es independiente del lenguaje: Python, Java, Go, PHP, C#, Rust o Swift lo leen y lo escriben con la misma facilidad. Por eso es el formato elegido para que sistemas heterogéneos se comuniquen.
Como JSON es texto, en JavaScript se puede guardar en una variable de tipo cadena, incluso con plantillas que insertan valores:
```javascript
const edad = 31;
const textoJson = `{
"nombre": "Ana",
"edad": ${edad}
}`;
```
Construir JSON a mano con plantillas es frágil, porque cualquier comilla o carácter especial en los valores romperá el documento. Para generarlo, la forma correcta es usar `JSON.stringify`.
## Convertir entre JSON y JavaScript
JavaScript incluye un objeto global llamado `JSON` con dos métodos fundamentales para pasar de un mundo al otro. Conviene no confundir este objeto, que es una utilidad del lenguaje, con el formato JSON en sí. Dominar **JSON.parse y JSON.stringify** es imprescindible en cualquier proyecto web.
`JSON.parse` convierte una cadena JSON en un valor de JavaScript:
```javascript
const respuesta = '{"producto":"Teclado","precio":49.9,"stock":12}';
const producto = JSON.parse(respuesta);
console.log(producto.precio * 2);
```
```shell
99.8
```
`JSON.stringify` hace lo contrario, convirtiendo un valor en una cadena JSON:
```javascript
const pedido = { id: 1042, total: 58.4, articulos: ['café', 'taza'] };
console.log(JSON.stringify(pedido));
```
```shell
{"id":1042,"total":58.4,"articulos":["café","taza"]}
```
El tercer argumento de `JSON.stringify` indica la indentación, útil para mostrar el resultado de forma legible o guardarlo en archivos:
```javascript
console.log(JSON.stringify({ a: 1, b: [1, 2] }, null, 2));
```
```shell
{
"a": 1,
"b": [
1,
2
]
}
```
El segundo argumento permite filtrar propiedades. Si es un array, solo se incluyen las claves indicadas, algo útil para no exponer datos sensibles:
```javascript
const usuario = { id: 1, nombre: 'Ana', contrasena: 'secreta' };
console.log(JSON.stringify(usuario, ['id', 'nombre']));
```
```shell
{"id":1,"nombre":"Ana"}
```
## Lo que se pierde al serializar
`JSON.stringify` no puede representar todos los valores de JavaScript, y es importante saber qué ocurre con cada uno para evitar sorpresas:
```javascript
const datos = {
nombre: 'Ana',
saludar: () => 'hola',
apodo: undefined,
alta: new Date(Date.UTC(2026, 9, 17)),
puntuacion: NaN,
};
console.log(JSON.stringify(datos));
```
```shell
{"nombre":"Ana","alta":"2026-10-17T00:00:00.000Z","puntuacion":null}
```
Las funciones y los valores `undefined` desaparecen; las fechas se convierten en cadenas ISO; y `NaN` e `Infinity` se convierten en `null`. Los `Map` y `Set` se serializan como objetos vacíos, y los `BigInt` provocan un error:
```shell
TypeError: Do not know how to serialize a BigInt
```
Las referencias circulares, un objeto que se contiene a sí mismo, también lanzan una excepción:
```shell
TypeError: Converting circular structure to JSON
```
Al volver a leer el JSON con `JSON.parse`, las fechas siguen siendo cadenas. Para reconstruirlas se usa el segundo argumento de `parse`, una función reviver que transforma cada valor:
```javascript
const texto = '{"fecha":"2026-10-17T00:00:00.000Z"}';
const objeto = JSON.parse(texto, (clave, valor) =>
clave === 'fecha' ? new Date(valor) : valor
);
console.log(objeto.fecha instanceof Date);
```
```shell
true
```
Un uso antiguo de `JSON.parse(JSON.stringify(obj))` era clonar objetos en profundidad. Hoy existe `structuredClone`, disponible en navegadores y en Node.js, que conserva fechas, `Map`, `Set` y referencias circulares.
Otra limitación menos conocida afecta a los números grandes. JavaScript solo representa enteros con exactitud hasta 2^53 - 1, así que los identificadores de 64 bits pierden precisión al analizarse:
```javascript
console.log(JSON.parse('12345678901234567890'));
```
```shell
12345678901234567000
```
Por eso muchas APIs, como la de X o la de Discord, envían los identificadores grandes como cadenas.
## JSON en otros lenguajes
En Python, el módulo `json` de la biblioteca estándar ofrece `loads` y `dumps` para cadenas, y `load` y `dump` para archivos:
```python
import json
empleado = {"nombre": "Lucía", "teletrabajo": True, "recomendado_por": None,
"ciudad": "Bogotá"}
texto = json.dumps(empleado, ensure_ascii=False)
print(texto)
with open("empleado.json", "w", encoding="utf-8") as archivo:
json.dump(empleado, archivo, ensure_ascii=False, indent=2)
with open("empleado.json", encoding="utf-8") as archivo:
datos = json.load(archivo)
```
```shell
{"nombre": "Lucía", "teletrabajo": true, "recomendado_por": null, "ciudad": "Bogotá"}
```
Python convierte `True`, `False` y `None` en `true`, `false` y `null` automáticamente. La opción `ensure_ascii=False` mantiene los caracteres acentuados en lugar de escaparlos como `\u00e1`.
En Go, los structs se mapean a JSON mediante etiquetas:
```go
type Empleado struct {
ID string `json:"id"`
Nombre string `json:"nombre"`
RecomendadoPor *string `json:"recomendado_por"`
}
var e Empleado
err := json.Unmarshal(datos, &e)
```
Y en Java, librerías como Jackson o Gson cumplen la misma función, convirtiendo objetos en JSON y viceversa.
## JSON en las APIs web
El uso más común de JSON es el intercambio de datos entre un cliente y un servidor a través de una API. Con `fetch`, recibir y enviar JSON es directo:
```javascript
const respuesta = await fetch('https://api.tienda.example/productos/42');
if (!respuesta.ok) throw new Error(`HTTP ${respuesta.status}`);
const producto = await respuesta.json();
await fetch('https://api.tienda.example/pedidos', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ productoId: 42, cantidad: 2 }),
});
```
El método `respuesta.json()` lee el cuerpo y lo analiza con `JSON.parse`. Al enviar datos, hay que serializarlos con `JSON.stringify` e indicar la cabecera `Content-Type: application/json`, para que el servidor sepa cómo interpretar el cuerpo.
En el lado del servidor, los frameworks modernos hacen esto de forma transparente. En Express, por ejemplo, el middleware `express.json()` analiza los cuerpos entrantes, y `res.json()` serializa las respuestas.
## Validar JSON con JSON Schema
Que un documento sea JSON válido no significa que tenga la estructura que tu aplicación espera. Un pedido puede llegar sin el campo `cantidad`, o con un precio negativo, y seguir siendo JSON perfectamente correcto.
El formato **JSON Schema es un estándar** para describir la estructura que debe tener un documento: qué campos son obligatorios, de qué tipo es cada uno y qué restricciones cumplen. El propio esquema se escribe en JSON:
```json
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["productoId", "cantidad"],
"properties": {
"productoId": { "type": "integer", "minimum": 1 },
"cantidad": { "type": "integer", "minimum": 1, "maximum": 99 },
"nota": { "type": "string", "maxLength": 200 }
},
"additionalProperties": false
}
```
Hay validadores para todos los lenguajes, como Ajv en JavaScript o `jsonschema` en Python. Validar en el servidor todo el JSON que llega desde fuera es una práctica de seguridad básica. En el ecosistema de TypeScript, librerías como Zod o Valibot cumplen una función similar y además infieren los tipos.
JSON Schema se usa también en especificaciones como OpenAPI, para documentar APIs, y en las salidas estructuradas de los modelos de lenguaje, donde el esquema garantiza que la respuesta del modelo tenga el formato esperado.
## Herramientas para trabajar con JSON
Algunas herramientas facilitan mucho el trabajo diario con este formato.
`jq` es una utilidad de línea de comandos para consultar y transformar JSON, imprescindible para trabajar con APIs desde la terminal:
```bash
curl -s https://api.tienda.example/empleados \
| jq '.usuarios[] | select(.edad > 30) | .nombre'
```
```shell
"Ana"
```
Los editores como Visual Studio Code validan la sintaxis mientras escribes, formatean el documento y, si el archivo declara un esquema, ofrecen autocompletado. Los navegadores muestran las respuestas JSON con un visor integrado. Y Python incluye un formateador desde la terminal:
```bash
python -m json.tool empleado.json
```
## Variantes y alternativas
La ausencia de comentarios y la rigidez de la sintaxis hacen que JSON sea incómodo para archivos de configuración escritos a mano. Por eso han surgido variantes. JSONC, JSON con comentarios, es el que usan VS Code y TypeScript en `tsconfig.json`. JSON5 añade comillas simples, claves sin comillas y comas finales. Ninguno es JSON estándar, así que no deben usarse para intercambiar datos entre sistemas.
Para procesar grandes volúmenes existe JSON Lines, o NDJSON, que guarda un documento JSON por línea. Permite leer los datos de forma secuencial sin cargar todo el archivo en memoria, y es habitual en logs y exportaciones de datos.
Frente a otros formatos, YAML es más legible para configuraciones y admite comentarios, pero su sintaxis basada en la indentación es más propensa a errores. XML sigue presente en sistemas empresariales y documentos, pero es mucho más verboso. Y formatos binarios como Protocol Buffers o MessagePack son más compactos y rápidos, a cambio de no ser legibles por personas.
## JSON en las bases de datos
JSON no solo viaja entre aplicaciones: también se almacena. Las bases de datos documentales, como MongoDB o CouchDB, guardan cada registro como un documento con estructura similar a JSON, lo que permite que cada uno tenga campos distintos sin modificar un esquema global.
Las bases de datos relacionales también lo han incorporado. PostgreSQL ofrece el tipo `jsonb`, que almacena el documento en un formato binario indexable y permite consultar su contenido con operadores específicos:
```sql
CREATE TABLE eventos (
id serial PRIMARY KEY,
datos jsonb NOT NULL
);
INSERT INTO eventos (datos)
VALUES ('{"tipo": "compra", "usuario": 87, "importe": 58.4}');
SELECT datos->>'tipo' AS tipo, (datos->>'importe')::numeric AS importe
FROM eventos
WHERE datos @> '{"tipo": "compra"}';
```
El operador `->>` extrae un campo como texto y `@>` comprueba si el documento contiene otro. Con un índice GIN sobre la columna, estas consultas son eficientes incluso con millones de filas. MySQL, SQLite y SQL Server ofrecen funciones equivalentes.
Guardar JSON en una base de datos relacional es útil para datos con estructura variable, como metadatos, preferencias de usuario o eventos de terceros. Para los datos centrales de la aplicación, que se consultan y relacionan con frecuencia, las columnas tradicionales siguen siendo la mejor opción.
## Buenas prácticas al diseñar documentos JSON
Algunas convenciones hacen que los documentos sean más claros y fáciles de mantener:
- Elige un estilo para las claves y mantenlo en toda la API: `camelCase` es habitual en JavaScript y `snake_case` en Python o Ruby.
- Usa el formato ISO 8601 con zona horaria para las fechas.
- Representa los identificadores largos y los importes monetarios exactos como cadenas o como enteros en céntimos, para evitar problemas de precisión.
- Distingue entre un campo ausente y un campo con valor `null`, y documenta qué significa cada caso.
- Evita anidar demasiados niveles; las estructuras planas son más fáciles de consultar y validar.
- Versiona tu API cuando cambies la estructura de forma incompatible.
- No incluyas nunca contraseñas, tokens ni datos personales innecesarios en las respuestas.
## Errores comunes y cómo resolverlos
Los errores de análisis de JSON son de los más frecuentes en desarrollo web. Los mensajes de las versiones actuales de Node.js y de los navegadores basados en Chromium son bastante descriptivos.
Claves sin comillas o con comillas simples:
```javascript
JSON.parse('{nombre: "Ana"}');
```
```shell
SyntaxError: Expected property name or '}' in JSON at position 1 (line 1 column 2)
```
Una coma después del último elemento:
```javascript
JSON.parse('{"a": 1,}');
```
```shell
SyntaxError: Expected double-quoted property name in JSON at position 7 (line 1 column 8)
```
Analizar algo que no es una cadena JSON, como `undefined`, normalmente porque una variable no se inicializó o una respuesta llegó vacía:
```shell
SyntaxError: "undefined" is not valid JSON
```
Y uno de los más habituales al trabajar con APIs: recibir HTML en lugar de JSON, porque el servidor devolvió una página de error. El mensaje indica que el primer carácter es `<`:
```shell
SyntaxError: Unexpected token '<', "<!DOCTYPE html>" is not valid JSON
```
Comprueba siempre `respuesta.ok` y la cabecera `Content-Type` antes de llamar a `respuesta.json()`, y revisa en la pestaña de red de las herramientas del navegador qué devolvió realmente el servidor.
En Python, el equivalente es `json.JSONDecodeError`:
```shell
json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
```
Por último, envuelve siempre en un bloque `try` el análisis de JSON que proceda de fuentes externas, para que un documento mal formado no detenga tu aplicación:
```javascript
function analizarSeguro(texto, porDefecto = null) {
try {
return JSON.parse(texto);
} catch {
return porDefecto;
}
}
```
## Conclusiones
JSON es un formato de texto sencillo para representar datos estructurados mediante pares clave-valor, objetos y arrays. Su sintaxis se reduce a unas pocas reglas, comillas dobles obligatorias, sin comas finales y sin comentarios, y admite solo seis tipos de valores: cadenas, números, booleanos, `null`, arrays y objetos.
Aunque nació a partir de la notación de objetos de JavaScript, JSON es texto e independiente del lenguaje, lo que lo ha convertido en el estándar para el intercambio de datos en APIs, configuraciones, bases de datos y logs. En JavaScript, `JSON.parse` y `JSON.stringify` convierten entre el texto y los valores del lenguaje, con matices importantes: las fechas se transforman en cadenas, las funciones y `undefined` desaparecen, y los números muy grandes pierden precisión.
Para trabajar con JSON de forma robusta conviene validar la estructura con JSON Schema o con librerías equivalentes, manejar los errores de análisis con `try`, comprobar las respuestas de las APIs antes de analizarlas y apoyarse en herramientas como `jq` y los validadores de los editores.
Con estos fundamentos, podrás diseñar documentos JSON claros, consumir y crear APIs con confianza y diagnosticar en segundos los errores que antes parecían misteriosos.
