Menu

JSON en Python: leer, escribir y parsear JSON con el módulo json

Cómo leer y escribir JSON en Python — loads, dumps, leer desde archivos, pretty printing y manejar los casos borde que aparecen con datos reales.

JSON y Python hablan las mismas formas

JSON es el formato por defecto para APIs, archivos de configuración e intercambio de datos en la web. Por suerte para los programadores de Python, un objeto JSON mapea directamente a un dict de Python, un array JSON a una lista, un string JSON a un str. Esa alineación cercana es por lo que leer y escribir JSON en Python es una operación de dos líneas.

El módulo de la librería estándar json maneja ambas direcciones.

Parsear un string JSON

json.loads(text) — "load string" — toma un string con formato JSON y devuelve el objeto Python que representa:

main.py
Output
Click Run to see the output here.

El resultado es un dict plano. Accedes a sus claves como en cualquier dict — sin envoltorio especial de JSON, sin método .parse() en el resultado.

Si el string no es JSON válido, json.loads lanza json.JSONDecodeError. El mensaje de error incluye la línea y columna del problema, que normalmente basta para detectar una coma que falta o una comilla sin escapar.

Escribir JSON como string

json.dumps(data) — "dump string" — hace lo contrario: toma un objeto Python y devuelve un string JSON:

main.py
Output
Click Run to see the output here.

True, False y None de Python se traducen a true, false y null de JSON automáticamente. Los números y strings pasan sin cambios. Las listas se convierten en arrays, los dicts en objetos.

Pretty printing

La salida por defecto de json.dumps es compacta — bien para transporte en red, difícil para humanos. Pasa indent=2 para algo más legible:

main.py
Output
Click Run to see the output here.

Unas cuantas otras opciones de dumps que vale la pena conocer:

  • sort_keys=True — ordena las claves de objeto alfabéticamente. Útil para salida determinista (archivos de configuración, fixtures de test, diffs).
  • ensure_ascii=False — escribe caracteres no-ASCII (é, ü, 中) como tal en vez de escapes \u. Normalmente la elección correcta para archivos UTF-8.
  • separators=(",", ":") — la salida más ajustada posible. Combinado con ensure_ascii=False, da el JSON UTF-8 más compacto que puedes producir.

Leer JSON desde un archivo

json.load(file) — sin s — lee directamente desde un objeto archivo. El patrón común lo empareja con with open:

import json

with open("config.json") as f:
    config = json.load(f)

print(config["version"])

No hace falta leer el archivo entero en un string primero; json.load hace streaming a través del objeto archivo.

Escribir JSON a un archivo

json.dump(data, file) es la contraparte de escritura a archivo:

import json

data = {"created": "2026-01-01", "items": [1, 2, 3]}

with open("state.json", "w") as f:
    json.dump(data, f, indent=2)

La opción indent también funciona aquí. Abre el archivo resultante y verás un documento JSON bien formateado.

Leer una respuesta de una API JSON

La mayoría de librerías HTTP te devuelven bytes o texto; llamas a json.loads para convertirlos en datos usables:

import json
import urllib.request

with urllib.request.urlopen("https://api.example.com/users/1") as response:
    text = response.read().decode("utf-8")

user = json.loads(text)
print(user["name"])

La librería requests (cubierta por separado) se salta un paso — tiene un método .json() en la respuesta que llama a json.loads por ti.

Qué puede y qué no puede representar JSON

El sistema de tipos de JSON es más estrecho que el de Python. El mapeo en ambas direcciones:

PythonJSON
dictobjeto
list, tuplearray
strstring
int, floatnúmero
Truetrue
Falsefalse
Nonenull

Las tuplas hacen round-trip como listas — la "tupleidad" se pierde. Los sets, las clases custom y los objetos datetime no se pueden serializar por defecto; obtienes TypeError: Object of type X is not JSON serializable.

Manejar datetime y objetos personalizados

Dos enfoques comunes.

Convierte a una estructura JSON-segura primero. Haz la transformación en tu propio código, luego serializa un dict plano:

main.py
Output
Click Run to see the output here.

Pasa una función default=. json.dumps la llama por cada valor que no sepa cómo serializar:

main.py
Output
Click Run to see the output here.

Cuando leas los datos de vuelta, necesitas convertir esos strings ISO a datetime tú — JSON no recuerda lo que eran originalmente.

Round-trip de un dict a través de JSON

Una comprobación rápida de que los dicts sobreviven:

main.py
Output
Click Run to see the output here.

Los valores son iguales, pero son objetos distintos. Eso suele ser lo que quieres — json.dumps + json.loads es una forma barata de hacer una copia profunda de cualquier estructura compatible con JSON.

Un ejemplo realista

Un pequeño script que carga una config JSON, actualiza un campo y la guarda de vuelta:

import json
from pathlib import Path

config_path = Path("settings.json")

# Cargar (con un default si el archivo no existe).
if config_path.exists():
    config = json.loads(config_path.read_text())
else:
    config = {"theme": "dark", "last_opened": None}

# Actualizar.
config["last_opened"] = "2026-01-15"

# Guardar, con pretty-print.
config_path.write_text(json.dumps(config, indent=2, ensure_ascii=False))

Ese es un ciclo completo "leer, modificar, escribir" de JSON en una docena de líneas.

Unos cuantos hábitos

  • Usa with open(...) para archivos, siempre. JSON es solo texto; todas las reglas de manejo de archivos aplican.
  • Prefiere indent=2 para archivos que leen humanos — configuración, fixtures, datos exportados. Sáltalo para tráfico de red donde la compactez importe.
  • Pon ensure_ascii=False para salida UTF-8 para que nombres con acentos o caracteres no-latinos queden legibles.
  • Valida con try/except json.JSONDecodeError cuando parsees datos que no produjiste tú.

Siguiente

JSON maneja datos clave-valor. La siguiente herramienta en el mismo capítulo es CSV — el soporte incorporado de Python para el formato tabular detrás de la mayoría de exportaciones de hoja de cálculo que te encontrarás.

Preguntas frecuentes

¿Cómo parseo JSON en Python?

Usa json.loads(text) para un string JSON o json.load(file) para un objeto archivo. Ambos devuelven un dict de Python (o una lista, dependiendo del JSON). Ejemplo: data = json.loads('{"name": "Rosa"}')data['name'] es 'Rosa'.

¿Cómo convierto un diccionario de Python a JSON?

json.dumps(my_dict) devuelve un string JSON. json.dump(my_dict, file) escribe directamente a un objeto archivo. Pasa indent=2 para salida con pretty-print: json.dumps(data, indent=2).

¿Cuál es la diferencia entre json.loads y json.load?

loads (con la s) toma un string. load (sin s) toma un objeto archivo. Igual para dumps vs dump. La s es por string; es la forma más fácil de recordar cuál es cuál.

¿Cómo manejo fechas y objetos personalizados en JSON?

JSON no tiene tipo date, así que pasa las fechas como strings ISO-8601 y parséalas de vuelta manualmente. Para clases personalizadas, o provee una función default= a json.dumps que devuelva una representación JSON-segura, o convierte a dict tú mismo antes de serializar.

Aprende a programar con Coddy

COMENZAR