StackPractices
beginner Por Mathias Paulenko

Parsear JSON en Python, JavaScript y Java

Parsea cadenas JSON a objetos nativos en Python, JavaScript y Java — con manejo de errores, streaming para archivos grandes y validación de esquema.

Temas: data

Visión General

Casi toda respuesta de API, payload de webhook y archivo de configuración que toques llega como texto JSON. Parsear convierte ese texto en datos nativos — diccionarios, objetos, POJOs — con los que tu código puede trabajar. Todos los lenguajes principales ofrecen una forma sólida de hacerlo, ya sea incorporada o mediante una librería estándar de facto.

Aquí encontrarás la forma idiomática de hacerlo en Python, JavaScript y Java — además de los errores que de verdad aparecen en producción y qué hacer cuando un archivo no cabe en memoria. Para la operación inversa, consulta Serializar y Deserializar Datos; para comprobar la estructura parseada contra un contrato, consulta Validar JSON Schema.

Cuándo Usar

Usa esta receta cuando:

  • Consumes una API REST que devuelve un payload JSON
  • Lees configuración o datos almacenados en archivos .json
  • Deserializas cuerpos de webhooks o eventos de una cola de mensajes
  • Conviertes una cadena JSON en objetos tipados de tu modelo de dominio — consulta Data Validation Zod para parsing basado en schemas

Cuándo Evitar

  • YAML o TOML para config editada por humanos: JSON no tiene comentarios ni strings multi-línea. Usa TOML o YAML para configuración escrita a mano.
  • Datos binarios: JSON codifica binario como base64, inflando el tamaño un tercio. Protobuf, MessagePack o CBOR funcionan mejor para payloads con mucho binario.
  • Archivos demasiado grandes para memoria: cambia a un parser de streaming (sección Avanzado); json.loads y JSON.parse necesitan la entrada completa en memoria.

Solución

Python

El módulo incorporado json es todo lo que necesitas:

import json

raw = '{"name": "Ada", "age": 36, "skills": ["math", "code"]}'
data = json.loads(raw)

print(data["name"])      # "Ada"
print(data["skills"][0])  # "math"

json.loads acepta str, bytes o bytearray. Para leer desde un archivo, usa json.load (sin la “s”) sobre el archivo abierto:

import json

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

Maneja siempre la entrada malformada: json.loads lanza JSONDecodeError, que además reporta dónde falló la entrada:

import json

try:
    data = json.loads(raw)
except json.JSONDecodeError as e:
    print(f"JSON inválido en línea {e.lineno}, col {e.colno}: {e.msg}")
    raise

JavaScript

JSON.parse viene incorporado. Un callback reviver permite convertir valores durante el parseo — el truco estándar para revivir objetos Date o arreglar números:

const raw = '{"name": "Ada", "age": 36, "skills": ["math", "code"]}';
const data = JSON.parse(raw);

console.log(data.name);       // "Ada"
console.log(data.skills[0]);  // "math"
const raw = '{"date": "2026-01-15", "count": "42"}';
const data = JSON.parse(raw, (key, value) => {
  if (key === 'count') return Number(value);
  if (key === 'date') return new Date(value);
  return value;
});
// data.date es un objeto Date, data.count es un número

La entrada inválida lanza un SyntaxError:

try {
  const data = JSON.parse(raw);
} catch (e) {
  if (e instanceof SyntaxError) {
    console.error('JSON inválido:', e.message);
  }
  throw e;
}

Java

Java no tiene parser incorporado, así que usa Jackson (com.fasterxml.jackson.core:jackson-databind) o Gson. Jackson ofrece dos estilos: un árbol navegable con readTree, o mapeo directo a un POJO con readValue:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;

ObjectMapper mapper = new ObjectMapper();
JsonNode node = mapper.readTree(
    "{\"name\": \"Ada\", \"age\": 36}");

String name = node.get("name").asText(); // "Ada"
int age = node.get("age").asInt();        // 36
public class User {
    public String name;
    public int age;
    public List<String> skills;
}

User user = mapper.readValue(jsonString, User.class);
try {
    User user = mapper.readValue(json, User.class);
} catch (JsonProcessingException e) {
    log.error("JSON inválido: {}", e.getOriginalMessage());
    throw new IllegalArgumentException("Bad request", e);
}

Explicación

Los tres lenguajes llegan a la misma idea con distinta ergonomía:

  • Python: json.loads sobre una cadena, json.load sobre un archivo; ambos devuelven dict/list. Hooks útiles: object_hook para construir objetos propios por cada objeto JSON, y parse_int/parse_float para controlar los tipos numéricos (p. ej. parse_float=Decimal para dinero).
  • JavaScript: JSON.parse devuelve objetos y arrays planos; el reviver opcional transforma cada valor de abajo hacia arriba. Nunca parsees JSON con eval(): ejecuta lo que sea que le pases.
  • Java: readTree de Jackson da un árbol JsonNode para acceso exploratorio; readValue enlaza directamente con tus clases y suele ser lo que quieres en código tipado.

Con los datos ya parseados, Llamar a una API REST muestra cómo obtener JSON por HTTP y Leer y Escribir Archivos cubre cómo cargarlo desde disco.

Variantes

LenguajeHerramientaDevuelveParsear desde archivo
Pythonjson (stdlib)dict / listjson.load(f)
JavaScriptJSON.parse() (nativo)Object / Arrayleer archivo y luego parsear
JavaJackson / GsonJsonNode / POJOmapper.readValue(file, T.class)
Goencoding/json (stdlib)map[string]interface{} / structjson.NewDecoder(r).Decode(&v)
Rustserde_json crateValue / structserde_json::from_reader(r)
C#System.Text.Json (stdlib)JsonElement / classJsonSerializer.Deserialize<T>(stream)

Avanzado: Streaming de Archivos JSON Grandes

Cuando un archivo no cabe en memoria, un parser de streaming recorre el documento token a token en lugar de materializar el árbol completo.

Python con ijson

import ijson

def process_large_json(file_path):
    with open(file_path, 'rb') as f:
        for item in ijson.items(f, 'items.item'):
            process(item)

Java con Jackson Streaming

try (JsonParser parser = mapper.getFactory().createParser(new File("large.json"))) {
    while (parser.nextToken() != JsonToken.END_OBJECT) {
        String fieldName = parser.getCurrentName();
        if ("items".equals(fieldName)) {
            parser.nextToken(); // START_ARRAY
            while (parser.nextToken() != JsonToken.END_ARRAY) {
                Item item = parser.readValueAs(Item.class);
                process(item);
            }
        }
    }
}

JavaScript con stream-json

const fs = require('fs');
const streamJson = require('stream-json');

const pipeline = fs.createReadStream('large.json')
  .pipe(streamJson.parser());

pipeline.on('data', (data) => {
  if (data.name === 'startArray') {
    // manejar inicio de array
  }
});

Avanzado: Validación con JSON Schema

Parsear te dice que el texto es JSON bien formado, no que tenga los campos que esperas. Para APIs propias, valida la estructura antes de confiar en ella:

import jsonschema

schema = {
    "type": "object",
    "properties": {
        "name": {"type": "string"},
        "age": {"type": "integer", "minimum": 0},
    },
    "required": ["name"],
}

jsonschema.validate(data, schema)  # lanza ValidationError si es inválido
const Ajv = require('ajv');
const ajv = new Ajv();
const validate = ajv.compile(schema);

if (!validate(data)) {
  console.error(validate.errors);
}

Lo que funciona

  • Maneja siempre los errores de parseo: envuelve el parseo en try/except (Python) o try/catch (JS/Java); el JSON externo no es de confianza.
  • Prefiere modelos tipados en Java: mapea a POJOs con readValue() en lugar de navegar JsonNode por claves de texto.
  • Nunca uses eval() en JavaScript: ejecuta código arbitrario; usa siempre JSON.parse().
  • Procesa payloads grandes en streaming: usa ijson (Python) o el JsonParser de Jackson para no cargar archivos enormes en memoria.
  • Valida contra un esquema: para APIs propias, valida con JSON Schema antes de confiar en la estructura.

Errores Comunes

  • Ignorar la codificación: JSON es UTF-8; leer un archivo con la codificación incorrecta corrompe los caracteres.
  • No capturar nada: el JSON malformado lanza una excepción; fallar en silencio es peor que devolver un 400 claro.
  • Precisión numérica en JavaScript: los enteros mayores que Number.MAX_SAFE_INTEGER pierden precisión; parsea los IDs grandes como cadenas.
  • Confundir loads y load: en Python, loads recibe una cadena y load recibe un archivo.
  • Asumir que las claves ignoran mayúsculas: no es así — Name y name son campos distintos.

Solución de Problemas

  • “Expecting value: line 1 column 1” (Python) o “Unexpected token” (JS): normalmente el cuerpo no es JSON en absoluto — una página de error HTML, un cuerpo vacío 204, o una redirección. Vuelca los primeros bytes de la respuesta para asegurarte.
  • Comas finales, comillas simples, claves sin comillas: eso es un literal de objeto JS o JSON5/JSONC, no JSON. Usa un parser tolerante (json5, jsonc-parser) — o mejor, arregla al productor.
  • UnicodeDecodeError o caracteres corruptos: el archivo probablemente tiene BOM o no es UTF-8. En Python, open(path, encoding="utf-8-sig") elimina el BOM limpiamente.
  • NaN / Infinity en el payload: no son JSON válido. JSON.parse los rechaza; json.loads de Python los acepta por defecto, así que un payload que parsea en desarrollo puede fallar más adelante.
  • Claves duplicadas: la mayoría de los parsers se quedan con el último valor sin avisar — en Python, object_pairs_hook permite detectar o rechazar duplicados.
  • RecursionError / stack overflow: anidamiento patológico u hostil. Las versiones recientes de Jackson limitan la profundidad (1000 por defecto) vía StreamReadConstraints.

Ver también

Preguntas frecuentes

¿Cómo parseo JSON desde un archivo en Python?

Usa json.load(f) (fíjate, load, no loads), pasando un archivo abierto: with open("data.json") as f: data = json.load(f). Pasa encoding="utf-8" explícitamente — JSON es UTF-8 por especificación.

¿Cuál es el equivalente en Java de json.loads de Python?

Usa ObjectMapper.readValue(String, Class<T>) cuando tienes una clase tipada, readTree(String) cuando no. Jackson acepta también archivos y streams: readValue(File, Class) y readValue(InputStream, Class).

¿Debo validar el JSON antes de parsearlo?

No puedes validar la estructura antes de parsear — la validación ocurre después, sobre los datos parseados. Para fuentes externas, el parseo defensivo con try/catch es lo mínimo; para APIs que controlas, valida con JSON Schema después de parsear.

¿Cómo manejo enteros grandes en JSON con JavaScript?

Los números en JavaScript son floats de 64 bits, así que los enteros más allá de Number.MAX_SAFE_INTEGER (2^53 - 1) pierden precisión. Usa una función reviver para parsear números grandes como strings: JSON.parse(raw, (k, v) => typeof v === 'number' && v > Number.MAX_SAFE_INTEGER ? String(v) : v). O recurre a BigInt con un parser personalizado.

¿Cómo parseo JSON con comentarios (JSONC)?

El JSON estándar no permite comentarios — lo encontrarás sobre todo en settings de VS Code o configuración editada a mano, donde JSONC es común. Parsea con jsonc-parser (npm) o json5 (Python/JS), o elimina los comentarios antes. Hagas lo que hagas, no recurras a eval().

¿Cuál es la diferencia entre JSON.parse y JSON.stringify?

JSON.parse toma una cadena JSON y devuelve un valor JavaScript; JSON.stringify recorre el camino opuesto. Son inversos, aunque stringify descarta en silencio valores undefined y funciones.

¿Cómo parseo streams JSON (NDJSON)?

NDJSON (newline-delimited JSON) lleva un objeto por línea — común en logs y exports de streaming. Python: [json.loads(line) for line in f if line.strip()]. Node.js: readline junto a JSON.parse. Java: un reader delimitado por líneas con ObjectMapper.readValues().

¿Qué es JSON5 y debería usarlo?

JSON5 es un superset de JSON que permite comentarios, comas finales, claves sin comillas y strings multi-línea — útil para configuración escrita a mano, y la librería json5 lo parsea. Para payloads de API, eso sí, quédate con JSON estándar: gana la interoperabilidad.

¿Cómo parseo JSON en Go?

Usa encoding/json del stdlib: var v MyStruct; err := json.Unmarshal([]byte(raw), &v). Para streaming, usa json.NewDecoder(r).Decode(&v). Go requiere campos de struct exportados con tags json:"fieldName" para el mapeo.

¿Cuál es el tamaño máximo de una cadena JSON?

La especificación no pone límite — los límites prácticos vienen de tu parser y tu memoria. El json de Python parsea hasta agotar la memoria disponible; JSON.parse topa con el límite del heap de JS (típicamente 2-4 GB). Más allá de ~1 GB, toca streaming.