Leer y escribir JSON en JavaScript

JSON nació de la sintaxis de los objetos de JavaScript, así que el lenguaje lo trae integrado: JSON.stringify convierte un objeto en texto y JSON.parse hace lo contrario. Funciona igual en el navegador y en Node.

De objeto a texto y vuelta

const pedido = {
  id: 1042,
  cliente: "Ana López",
  productos: [
    { nombre: "Teclado", precio: 49.9, cantidad: 1 },
    { nombre: "Ratón", precio: 19.5, cantidad: 2 },
  ],
  pagado: false,
};

const compacto = JSON.stringify(pedido);
console.log(compacto);

const legible = JSON.stringify(pedido, null, 2);
console.log(legible);

const deVuelta = JSON.parse(compacto);
console.log(deVuelta.productos[1].nombre, deVuelta.productos.length);
salida{"id":1042,"cliente":"Ana López","productos":[{"nombre":"Teclado","precio":49.9,"cantidad":1},{"nombre":"Ratón","precio":19.5,"cantidad":2}],"pagado":false}
{
  "id": 1042,
  "cliente": "Ana López",
  "productos": [
    {
      "nombre": "Teclado",
      "precio": 49.9,
      "cantidad": 1
    },
    {
      "nombre": "Ratón",
      "precio": 19.5,
      "cantidad": 2
    }
  ],
  "pagado": false
}
Ratón 2

JSON.stringify(pedido) da una sola línea, ideal para enviar por la red. Con JSON.stringify(pedido, null, 2) sale con sangría de dos espacios, que es lo que quieres para un archivo que va a leer una persona. El segundo argumento, null, es un filtro opcional que veremos más abajo.

JSON.stringify convierte un objeto en texto y JSON.parse hace lo contrarioJSON.stringify y JSON.parse: de objeto a texto y vueltaobjeto de JavaScript{ id: 1042,  cliente: ‘Ana’,  pagado: false }texto (una cadena){«id»:1042, «cliente»:»Ana», «pagado»:false}JSON.stringifyJSON.parsePor el camino se pierden undefined, las funciones, Set y Map,y las fechas vuelven convertidas en texto.

El objeto vive en la memoria del programa; el JSON es solo texto, que se puede guardar o enviar. Esquema: decodigo.com.

Guardar y leer un archivo JSON

import { readFile, writeFile } from "node:fs/promises";

const config = { tema: "oscuro", idioma: "es", avisos: { correo: true, sms: false } };
await writeFile("config.json", JSON.stringify(config, null, 2) + "\n", "utf8");

const leida = JSON.parse(await readFile("config.json", "utf8"));
leida.idioma = "pt";
await writeFile("config.json", JSON.stringify(leida, null, 2) + "\n", "utf8");

console.log(await readFile("config.json", "utf8"));
salida{
  "tema": "oscuro",
  "idioma": "pt",
  "avisos": {
    "correo": true,
    "sms": false
  }
}

El patrón es siempre el mismo: leer el texto, JSON.parse, cambiar el objeto y JSON.stringify para guardar. El + "\n" deja un salto de línea al final, como esperan los editores y Git.

Importar un JSON directamente

Si el archivo es fijo, como una configuración que viaja con el programa, se puede importar como si fuera un módulo:

import config from "./config.json" with { type: "json" };

console.log(config.tema, config.avisos.correo);
salidaoscuro true

El with { type: "json" } es obligatorio: le dice a Node que no ejecute el archivo como código. Ojo, se lee una sola vez, al arrancar: si el archivo cambia mientras el programa corre, no te enterarás. Para eso, readFile.

Lo que JSON no sabe guardar

JSON solo conoce cadenas, números, booleanos, null, arrays y objetos. Todo lo demás se pierde o se transforma, y sin avisar:

const datos = {
  nombre: "Ana",
  apodo: undefined,
  saludar() { return "hola"; },
  alta: new Date("2026-10-19T08:30:00Z"),
  etiquetas: new Set(["a", "b"]),
  nada: null,
  infinito: Infinity,
};
const json = JSON.stringify(datos);
console.log(json);

const otra = JSON.parse(json);
console.log(typeof otra.alta, otra.alta);
salida{"nombre":"Ana","alta":"2026-10-19T08:30:00.000Z","etiquetas":{},"nada":null,"infinito":null}
string 2026-10-19T08:30:00.000Z
ValorQué hace JSON.stringify
undefined y funcionesLa propiedad desaparece
DateSe convierte en texto ISO; al leerlo vuelve como cadena, no como fecha
Set y MapSe quedan en {}, vacíos
Infinity y NaNSe convierten en null
BigIntLanza un TypeError

Recuperar las fechas y filtrar campos

JSON.parse acepta una función, el reviver, que ve cada clave y su valor y puede cambiarlo. Es la forma limpia de recuperar las fechas. Y JSON.stringify acepta una lista de claves permitidas, útil para no sacar datos sensibles:

const json = '{"nombre":"Ana","alta":"2026-10-19T08:30:00.000Z"}';

const usuario = JSON.parse(json, (clave, valor) =>
  clave === "alta" ? new Date(valor) : valor
);
console.log(usuario.alta instanceof Date, usuario.alta.getUTCFullYear());

const filtrado = JSON.stringify({ nombre: "Ana", clave: "1234", edad: 34 }, ["nombre", "edad"]);
console.log(filtrado);
salidatrue 2026
{"nombre":"Ana","edad":34}

Los errores más comunes

const texto = "{'nombre': 'Ana'}";
try {
  JSON.parse(texto);
} catch (err) {
  console.log(err.name + ": " + err.message);
}
try {
  JSON.parse('{"a": 1,}');
} catch (err) {
  console.log(err.name + ": " + err.message);
}
try {
  JSON.stringify({ id: 10n });
} catch (err) {
  console.log(err.name + ": " + err.message);
}
const a = { nombre: "a" };
a.yo = a;
try {
  JSON.stringify(a);
} catch (err) {
  console.log(err.name + ": " + err.message);
}
salidaSyntaxError: Expected property name or '}' in JSON at position 1 (line 1 column 2)
SyntaxError: Expected double-quoted property name in JSON at position 8 (line 1 column 9)
TypeError: Do not know how to serialize a BigInt
TypeError: Converting circular structure to JSON
    --> starting at object with constructor 'Object'
    --- property 'yo' closes the circle

Los dos primeros son JSON mal escrito: en JSON las claves y las cadenas van siempre con comillas dobles, y no se admite una coma tras el último elemento, aunque en JavaScript sí. El mensaje dice la línea y la columna exactas. Los otros dos son datos que JSON no puede representar: un BigInt y un objeto que se contiene a sí mismo.

Un JSON.parse de datos que vienen de fuera, siempre dentro de try/catch. Un archivo editado a mano o una respuesta de un servidor caído pueden traer cualquier cosa, y un SyntaxError sin capturar tumba el programa.

Todo el código de esta página se ejecutó con Node.js 24.22 en un contenedor limpio antes de publicarla; las salidas, incluidos los errores, están copiadas de esa ejecución. Documentación oficial: el objeto JSON en MDN.