JSON en Python: leer, escribir y validar datos

Publicado el: 11/07/2026
Tempo de leitura: 4 minutos
Manipulação de dados JSON em Python

JSON es uno de los formatos más utilizados para intercambiar datos entre aplicaciones. APIs, servicios web, archivos de configuración y muchas herramientas almacenan información como objetos, listas, números, textos, booleanos y valores nulos. Python incluye el módulo json en su biblioteca estándar, por lo que puedes trabajar con este formato sin instalar paquetes adicionales.

Para aprovechar esta guía, repasa los diccionarios, las listas, los strings, el manejo de excepciones y la guía de Requests. Consulta también la documentación oficial del módulo json y la especificación RFC 8259.

Qué es JSON

JSON significa JavaScript Object Notation, pero se utiliza con muchos lenguajes. Un documento puede verse así:

{
  "nombre": "Ana",
  "edad": 30,
  "activo": true,
  "roles": ["editor", "autor"],
  "telefono": null
}

Las claves deben estar entre comillas dobles. Los valores booleanos son true y false, y la ausencia se representa con null.

Equivalencias con Python

  • Objeto JSON → dict
  • Array JSON → list
  • String JSON → str
  • Número entero → int
  • Número decimal → float
  • true/falseTrue/False
  • nullNone

Convertir un string JSON a Python

import json

texto = '''
{
  "nombre": "Ana",
  "edad": 30,
  "activo": true
}
'''

datos = json.loads(texto)
print(datos["nombre"])
print(type(datos))

loads significa “load string”. Devuelve estructuras de Python.

Convertir Python a JSON

usuario = {
    "nombre": "Luis",
    "edad": 25,
    "activo": True,
    "telefono": None,
}

texto_json = json.dumps(usuario)
print(texto_json)

dumps produce un string. Observa que True se convierte en true y None en null.

Crear JSON legible

texto_json = json.dumps(
    usuario,
    ensure_ascii=False,
    indent=2,
)

indent añade sangría. ensure_ascii=False conserva caracteres como á, ñ y ç en vez de escribir secuencias escapadas. La codificación del archivo seguirá siendo importante.

Guardar JSON en un archivo

from pathlib import Path
import json

ruta = Path("usuario.json")

with ruta.open("w", encoding="utf-8") as archivo:
    json.dump(
        usuario,
        archivo,
        ensure_ascii=False,
        indent=2,
    )

dump escribe directamente en un archivo abierto. Especificar UTF-8 evita depender de la configuración regional.

Leer un archivo JSON

with ruta.open("r", encoding="utf-8") as archivo:
    datos = json.load(archivo)

print(datos.get("nombre"))

load trabaja con un archivo; loads, con un string. La misma diferencia se aplica a dump y dumps.

Manejar errores de sintaxis

try:
    datos = json.loads('{"nombre": "Ana",}')
except json.JSONDecodeError as error:
    print(f"JSON inválido en línea {error.lineno}, columna {error.colno}")

JSON no permite comas finales, comentarios, claves sin comillas ni comillas simples como delimitadores estándar.

Manejar archivos ausentes

try:
    with Path("config.json").open("r", encoding="utf-8") as archivo:
        config = json.load(archivo)
except FileNotFoundError:
    config = {}
except json.JSONDecodeError as error:
    raise RuntimeError(f"Configuración inválida: {error}") from error

No conviene tratar un archivo corrupto como si estuviera vacío sin avisar. La estrategia depende de la importancia del dato.

Validar la estructura

Que un documento sea JSON válido no significa que tenga los campos correctos:

def validar_usuario(datos):
    if not isinstance(datos, dict):
        raise ValueError("Se esperaba un objeto")

    nombre = datos.get("nombre")
    edad = datos.get("edad")

    if not isinstance(nombre, str) or not nombre.strip():
        raise ValueError("Nombre inválido")
    if not isinstance(edad, int) or edad < 0:
        raise ValueError("Edad inválida")

Para proyectos grandes puedes usar JSON Schema, dataclasses o bibliotecas de validación, pero las reglas deben seguir siendo explícitas.

Listas de objetos

productos = [
    {"id": 1, "nombre": "Teclado", "precio": 50.0},
    {"id": 2, "nombre": "Ratón", "precio": 20.0},
]

with Path("productos.json").open("w", encoding="utf-8") as archivo:
    json.dump(productos, archivo, ensure_ascii=False, indent=2)

Al leerlos, confirma que el nivel principal sea una lista y que cada elemento sea un diccionario.

Ordenar claves

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

sort_keys puede ser útil en tests, comparaciones y archivos generados automáticamente. No debe confundirse con el orden semántico de una interfaz.

Tipos que JSON no soporta directamente

JSON no conoce fechas, sets, bytes, rutas ni objetos personalizados:

from datetime import datetime

registro = {
    "fecha": datetime.now(),
}

json.dumps(registro) producirá TypeError. Convierte explícitamente:

registro["fecha"] = registro["fecha"].isoformat()

Al leer, puedes reconstruir la fecha con datetime.fromisoformat.

Usar default con cuidado

from pathlib import Path
import json


def convertir(objeto):
    if isinstance(objeto, Path):
        return str(objeto)
    raise TypeError(f"Tipo no serializable: {type(objeto).__name__}")

texto = json.dumps({"ruta": Path("datos.txt")}, default=convertir)

No conviertas silenciosamente cualquier objeto con str, porque puedes perder información y ocultar errores.

Decimales y precisión

Por defecto, los números decimales se convierten en float. Para datos financieros puedes usar Decimal al leer:

from decimal import Decimal

texto = '{"precio": 19.90}'
datos = json.loads(texto, parse_float=Decimal)

Para escribir un Decimal debes definir cómo representarlo, por ejemplo como string, y documentar esa decisión.

JSON de una API

import requests

respuesta = requests.get(
    "https://api.example.com/productos",
    timeout=10,
)
respuesta.raise_for_status()
datos = respuesta.json()

respuesta.json() puede fallar si el servidor devuelve HTML o contenido inválido. Valida también el encabezado y la estructura.

No confundir JSON con un diccionario

Un diccionario es un objeto en memoria. JSON es texto:

datos = {"activo": True}           # dict
texto = '{"activo": true}'         # str con JSON

No uses eval para convertir JSON. Además de ser incorrecto, puede ejecutar código peligroso. Usa siempre json.loads.

Escritura segura

Si el archivo es importante, escribe primero en una ruta temporal y reemplaza el original:

ruta = Path("config.json")
temporal = ruta.with_suffix(".tmp")

temporal.write_text(
    json.dumps(config, ensure_ascii=False, indent=2),
    encoding="utf-8",
)
temporal.replace(ruta)

Esto reduce el riesgo de dejar un archivo parcialmente escrito.

JSON Lines

Para registros grandes puede utilizarse un objeto JSON por línea:

with Path("eventos.jsonl").open("a", encoding="utf-8") as archivo:
    evento = {"tipo": "login", "usuario": 10}
    archivo.write(json.dumps(evento, ensure_ascii=False) + "\n")

JSON Lines permite procesar registros uno por uno sin cargar todo el archivo, aunque no es un único documento JSON convencional.

Seguridad

No guardes contraseñas, tokens o claves secretas en JSON dentro del repositorio. No confíes en datos recibidos de usuarios. Limita tamaños, valida tipos y evita usar campos JSON directamente para construir consultas SQL, rutas o comandos.

Pruebas

def test_conversion_json():
    original = {"nombre": "Ana", "roles": ["editor"]}
    texto = json.dumps(original, ensure_ascii=False)
    recuperado = json.loads(texto)
    assert recuperado == original

Añade casos con Unicode, valores nulos, listas vacías, JSON inválido, campos ausentes y números grandes.

Errores frecuentes

Los problemas habituales son usar comillas simples en el documento, dejar una coma final, confundir load con loads, no especificar UTF-8, asumir que todos los campos existen y serializar tipos no compatibles. También es común guardar datos ya formateados en lugar de valores estructurados.

Conclusión

El módulo json permite convertir entre texto JSON y estructuras de Python, leer y escribir archivos y procesar respuestas de APIs. Utiliza load/dump para archivos y loads/dumps para strings. Valida siempre la estructura, maneja errores, protege secretos y define cómo representar fechas, decimales y objetos especiales.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    Símbolo de repetição ao lado do logotipo do Python pensativo, representando o conceito de loops na programação em Python.
    Fundamentos
    Foto de perfil de Leandro Hirt da Academify

    Bucles en Python: for y while explicados con ejemplos

    Aprende bucles for y while en Python con range, enumerate, zip, break, continue, else, comprensiones, generadores y ejemplos prácticos.

    Ler mais

    Tempo de leitura: 5 minutos
    11/07/2026
    ícone de loop com o texto 'While' abaixo
    Fundamentos
    Foto de perfil de Leandro Hirt da Academify

    Bucles while en Python: guía práctica para principiantes

    Aprende bucles while en Python con condiciones, validación, menús, break, continue, else, centinelas, reintentos y buenas prácticas.

    Ler mais

    Tempo de leitura: 5 minutos
    11/07/2026
    Imagem de um quadro negro com várias interrogações no lugar de lâmpadas, e uma lâmpada conectada no meio
    Fundamentos
    Foto de perfil de Leandro Hirt da Academify

    If, elif y else en Python: guía de decisiones

    Aprende if, elif y else en Python con comparaciones, operadores lógicos, validación, rangos, menús, retornos tempranos y pruebas.

    Ler mais

    Tempo de leitura: 4 minutos
    11/07/2026
    Homem pensando à frente de um notebook com código de programação
    Fundamentos
    Foto de perfil de Leandro Hirt da Academify

    Indentación en Python: guía clara para principiantes

    Aprende indentación en Python, cuatro espacios, bloques, IndentationError, TabError, errores lógicos y configuración correcta del editor.

    Ler mais

    Tempo de leitura: 5 minutos
    11/07/2026
    Logo do Python com símbolos de lista, tupla e dicionário
    Fundamentos
    Foto de perfil de Leandro Hirt da Academify

    Lista vs tupla vs set vs diccionario en Python

    Compara listas, tuplas, sets y diccionarios en Python según orden, mutabilidad, duplicados, búsquedas, conversiones y casos de uso.

    Ler mais

    Tempo de leitura: 5 minutos
    11/07/2026
    Programador pensnado em frente à vários monitores com código na tela
    Fundamentos
    Foto de perfil de Leandro Hirt da Academify

    15 ejercicios de Python para principiantes con soluciones

    Practica Python con 15 ejercicios resueltos sobre entrada, condiciones, bucles, funciones, listas, diccionarios, archivos y validación.

    Ler mais

    Tempo de leitura: 4 minutos
    11/07/2026