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.
También te puede interesar
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 2JSON.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.
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| Valor | Qué hace JSON.stringify |
|---|---|
undefined y funciones | La propiedad desaparece |
Date | Se convierte en texto ISO; al leerlo vuelve como cadena, no como fecha |
Set y Map | Se quedan en {}, vacíos |
Infinity y NaN | Se convierten en null |
BigInt | Lanza 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 circleLos 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.
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.