W3docs

Python JSON

Aprende a usar el módulo json de Python para codificar, decodificar, leer y escribir datos JSON, con ejemplos prácticos y manejo de errores.

El módulo integrado json de Python te permite convertir entre objetos Python y texto JSON con solo dos funciones en la mayoría de los casos. Este capítulo cubre todo lo que necesitas: mapeo de tipos de datos, dumps/loads para cadenas, dump/load para archivos, impresión con formato, manejo de errores y serialización personalizada.

¿Qué es JSON?

JSON (JavaScript Object Notation) es un formato de intercambio de datos ligero y basado en texto. Es legible por humanos, independiente del lenguaje y el formato predeterminado para la mayoría de las APIs web.

Un documento JSON está formado por dos estructuras:

  • Objetos — colecciones desordenadas de pares clave/valor encerradas en {}. Las claves siempre son cadenas entre comillas dobles.
  • Arrays — secuencias ordenadas de valores encerradas en [].

Ejemplo de documento JSON:

{
  "name": "John Doe",
  "age": 30,
  "city": "New York",
  "hobbies": ["reading", "traveling", "photography"],
  "active": true,
  "score": null
}

Mapeo de tipos Python–JSON

Al codificar o decodificar JSON, el módulo json de Python convierte los tipos según esta tabla:

Tipo PythonTipo JSONTipo Python (tras decodificar)
dictobject {}dict
list, tuplearray []list
strstring ""str
int, floatnumberint o float
True / Falsetrue / falsebool
NonenullNone

Ten en cuenta que las tuplas se convierten en arrays JSON y vuelven como listas Python tras la decodificación.

Codificar objetos Python a cadenas JSON

json.dumps() (dump-string) serializa un objeto Python en una cadena con formato JSON.

Codificación básica

python— editable, runs on the server

Salida:

{"name": "John Doe", "age": 30, "city": "New York", "hobbies": ["reading", "traveling", "photography"]}

Impresión con formato usando indent y sort_keys

Por defecto, json.dumps() produce una cadena compacta en una sola línea. Pasa indent para obtener una salida legible por humanos, y sort_keys=True para ordenar las claves del diccionario alfabéticamente:

import json

person = {
    "name": "John Doe",
    "age": 30,
    "city": "New York",
    "hobbies": ["reading", "traveling", "photography"]
}

print(json.dumps(person, indent=2, sort_keys=True))

Salida:

{
  "age": 30,
  "city": "New York",
  "hobbies": [
    "reading",
    "traveling",
    "photography"
  ],
  "name": "John Doe"
}

Usa indent=2 o indent=4 al escribir archivos de configuración o depurar respuestas de API — facilita la lectura de estructuras anidadas.

Decodificar cadenas JSON a objetos Python

json.loads() (load-string) analiza una cadena JSON y devuelve el objeto Python equivalente.

Decodificación básica

python— editable, runs on the server

Salida:

{'name': 'John Doe', 'age': 30, 'city': 'New York', 'hobbies': ['reading', 'traveling', 'photography']}
<class 'dict'>
John Doe

El valor decodificado es un diccionario Python normal, por lo que puedes acceder a sus claves con [] o .get(), iterarlo con for, etc.

Manejo de JSON mal formado

Si la entrada no es JSON válido, json.loads() lanza json.JSONDecodeError. Captúralo siempre al trabajar con datos de fuentes externas:

import json

raw = '{"name": "Alice", "age":}'   # invalid — missing value

try:
    data = json.loads(raw)
except json.JSONDecodeError as e:
    print(f"Invalid JSON: {e}")

Salida:

Invalid JSON: Expecting value: line 1 column 24 (char 23)

Consulta el capítulo Python try/except para una guía completa del manejo de excepciones.

Trabajar con JSON anidado

Los objetos JSON pueden contener otros objetos y arrays a cualquier profundidad. Accede a los valores anidados usando la notación [] encadenada:

python— editable, runs on the server

Salida:

John
traveling

Para estructuras muy anidadas, considera usar .get() con un valor predeterminado para evitar KeyError en claves ausentes:

city = person.get("address", {}).get("city", "unknown")

El capítulo de diccionarios anidados cubre patrones para trabajar con dicts Python profundamente anidados.

Leer y escribir archivos JSON

json.dump() escribe en un objeto de archivo, y json.load() lee de uno. Son los equivalentes para archivos de dumps/loads.

Escribir JSON en un archivo

import json

data = {"name": "Alice", "scores": [95, 87, 92]}

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

Esto crea data.json con contenido formateado. Usar with open(...) garantiza que el archivo se cierre automáticamente — consulta manejo de archivos en Python para más detalles.

Leer JSON desde un archivo

import json

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

print(data)
print(data["scores"])

Salida (asumiendo el archivo escrito anteriormente):

{'name': 'Alice', 'scores': [95, 87, 92]}
[95, 87, 92]

Ejemplo de ciclo completo

import json

# Write
config = {"host": "localhost", "port": 5432, "debug": False}
with open("config.json", "w") as f:
    json.dump(config, f, indent=2)

# Read back
with open("config.json") as f:
    loaded = json.load(f)

print(loaded["port"])   # 5432
print(type(loaded["port"]))   # <class 'int'>

Obtener JSON desde una API web

En la mayoría de los proyectos decodificarás JSON que proviene de una respuesta HTTP. La popular biblioteca requests lo hace sencillo:

import requests

response = requests.get("https://jsonplaceholder.typicode.com/todos/1")
response.raise_for_status()   # raises an error for 4xx/5xx responses
data = response.json()        # equivalent to json.loads(response.text)

print(data["title"])
print(data["completed"])

response.json() llama a json.loads() internamente. Llama siempre a raise_for_status() antes de analizar para que una solicitud fallida no devuelva silenciosamente un cuerpo de error.

Serialización personalizada con default

El módulo json no puede codificar objetos Python arbitrarios (como datetime.date) por defecto. Pasa un callable default o una subclase personalizada de JSONEncoder para manejarlos:

import json
import datetime

class DateEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime.date):
            return obj.isoformat()
        return super().default(obj)

event = {"name": "Conference", "date": datetime.date(2024, 1, 15)}
print(json.dumps(event, cls=DateEncoder))

Salida:

{"name": "Conference", "date": "2024-01-15"}

El objeto date se convierte a su cadena ISO 8601 antes de la serialización.

Deserialización personalizada con object_hook

object_hook se llama para cada objeto JSON (dict) al ser decodificado. Puedes usarlo para transformar datos al vuelo — por ejemplo, convirtiendo valores de cadena a los tipos Python correctos:

import json

def as_record(d):
    """Convert age field from string to int if present."""
    if "age" in d:
        d["age"] = int(d["age"])
    return d

raw = '{"name": "Bob", "age": "25"}'
person = json.loads(raw, object_hook=as_record)
print(person)
print(type(person["age"]))   # <class 'int'>

Salida:

{'name': 'Bob', 'age': 25}
<class 'int'>

Referencia rápida

FunciónDirecciónOrigen/destino
json.dumps(obj)Python → JSONdevuelve un str
json.loads(s)JSON → Pythonlee desde un str
json.dump(obj, f)Python → JSONescribe en un archivo
json.load(f)JSON → Pythonlee desde un archivo

Parámetros opcionales clave:

  • indent=2 — impresión con formato usando 2 espacios de sangría
  • sort_keys=True — ordenar las claves del diccionario alfabéticamente
  • cls=MyEncoder — usar una subclase personalizada de JSONEncoder
  • object_hook=fn — transformar cada object dict decodificado

Práctica

Práctica
Which Python function converts a Python dictionary to a JSON-formatted string?
Which Python function converts a Python dictionary to a JSON-formatted string?
Was this page helpful?