Saltar a contenido

Ficheros JSON

Introducción

JSON (JavaScript Object Notation) es un formato de texto para representar datos estructurados. Es legible por humanos y fácilmente procesable por máquinas.

Ejemplo de fichero alumno.json:

{
    "nombre": "Ana García",
    "ciclo": "DAW",
    "nota": 8.5,
    "modulos": ["Programación", "Bases de Datos", "Entornos de Desarrollo"],
    "aprobado": true
}

JSON soporta los siguientes tipos de datos:

Tipo JSON Equivalente en Python
string str
number int o float
boolean (true/false) bool (True/False)
null None
array list
object dict

JSON es ideal para:

  • Almacenar datos con estructura compleja o anidada
  • Comunicar datos entre aplicaciones (APIs REST)
  • Ficheros de configuración de aplicaciones
  • Fichas de alumnos con información detallada

Usa CSV para datos tabulares simples (como un listado) y JSON cuando los datos tienen estructura jerárquica o campos opcionales.

El módulo json

Python incluye el módulo json en la biblioteca estándar:

import json

Las cuatro funciones principales son:

Función Dirección Origen/Destino
json.load() JSON → Python fichero
json.loads() JSON → Python string
json.dump() Python → JSON fichero
json.dumps() Python → JSON string

Leer JSON desde un fichero: json.load()

1
2
3
4
5
6
7
8
import json

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

print(alumno["nombre"])   # Ana García
print(alumno["nota"])     # 8.5
print(alumno["modulos"])  # ['Programación', 'Bases de Datos', 'Entornos de Desarrollo']

json.load() convierte automáticamente los tipos JSON a sus equivalentes en Python.

Leer una lista de alumnos desde JSON

alumnos.json
[
    {"nombre": "Ana García",      "ciclo": "DAW",  "nota": 8.5},
    {"nombre": "Carlos López",    "ciclo": "DAM",  "nota": 6.0},
    {"nombre": "María Fernández", "ciclo": "DAW",  "nota": 9.2},
    {"nombre": "Pedro Martín",    "ciclo": "ASIR", "nota": 5.5}
]
1
2
3
4
5
6
7
import json

with open("alumnos.json", "r", encoding="utf-8") as f:
    alumnos = json.load(f)   # devuelve una lista de diccionarios

for alumno in alumnos:
    print(f"{alumno['nombre']} ({alumno['ciclo']}): {alumno['nota']}")
Ana García (DAW): 8.5
Carlos López (DAM): 6.0
María Fernández (DAW): 9.2
Pedro Martín (ASIR): 5.5

Leer JSON desde un string: json.loads()

json.loads() (con la s de string) convierte una cadena JSON a un objeto Python. Es útil cuando los datos llegan como texto (por ejemplo, desde una API):

1
2
3
4
5
6
import json

texto = '{"nombre": "Ana García", "nota": 8.5}'
alumno = json.loads(texto)

print(alumno["nombre"])   # Ana García

Escribir JSON en un fichero: json.dump()

import json

alumno = {
    "nombre": "Ana García",
    "ciclo": "DAW",
    "nota": 8.5,
    "modulos": ["Programación", "Bases de Datos"],
    "aprobado": True
}

with open("alumno.json", "w", encoding="utf-8") as f:
    json.dump(alumno, f, indent=4, ensure_ascii=False)

El fichero alumno.json resultante:

{
    "nombre": "Ana García",
    "ciclo": "DAW",
    "nota": 8.5,
    "modulos": [
        "Programación",
        "Bases de Datos"
    ],
    "aprobado": true
}

Los parámetros más útiles de json.dump():

  • indent: número de espacios para el indentado (hace el JSON legible). Si es None, escribe todo en una línea.
  • ensure_ascii=False: permite escribir caracteres no ASCII (tildes, ñ) directamente en lugar de codificarlos como \u00f3.

Escribir JSON a un string: json.dumps()

json.dumps() convierte un objeto Python a una cadena JSON sin escribirla en disco:

1
2
3
4
5
6
import json

alumno = {"nombre": "Ana García", "nota": 8.5}

texto = json.dumps(alumno, indent=2, ensure_ascii=False)
print(texto)
{
  "nombre": "Ana García",
  "nota": 8.5
}

Limitaciones de serialización

No todos los tipos de Python se pueden serializar directamente a JSON. Los más habituales que no funcionan son: datetime, objetos de clases propias, set, tuple (se convierte a lista).

1
2
3
4
5
import json
from datetime import date

datos = {"nombre": "Ana", "fecha_nacimiento": date(2000, 5, 12)}
json.dumps(datos)   # TypeError: Object of type date is not JSON serializable

La solución más sencilla es convertir el valor a string antes de serializar:

1
2
3
4
5
6
import json
from datetime import date

datos = {"nombre": "Ana", "fecha_nacimiento": str(date(2000, 5, 12))}
print(json.dumps(datos, ensure_ascii=False))
# {"nombre": "Ana", "fecha_nacimiento": "2000-05-12"}

Antipatrón: usar eval() para leer JSON

# Incorrecto: eval() ejecuta cualquier código Python, es un agujero de seguridad
with open("alumno.json", "r", encoding="utf-8") as f:
    alumno = eval(f.read())
# Correcto: json.load() es seguro y específico para JSON
import json
with open("alumno.json", "r", encoding="utf-8") as f:
    alumno = json.load(f)

Antipatrón: olvidar ensure_ascii=False con texto en español

# Incorrecto: los caracteres especiales se codifican como secuencias de escape
import json
json.dumps({"nombre": "María"})
# '{"nombre": "Mar\\u00eda"}'  — difícil de leer
# Correcto: el texto español se escribe tal cual
json.dumps({"nombre": "María"}, ensure_ascii=False)
# '{"nombre": "María"}'