Curso de Python / Convertir y guardar datos JSON
JSON, abreviatura de JavaScript Object Notation, es un formato de texto para datos estructurados. json.load() y dump() trabajan con archivos, mientras que loads() y dumps() trabajan con cadenas; el formato no conserva cualquier objeto o tipo posible de Python.
Relacionar los valores JSON con Python
| JSON | Python |
|---|---|
| object | dict |
| array | list |
| string | str |
| true / false / null | True / False / None |
Las claves y cadenas JSON utilizan comillas dobles. Las comillas simples propias de algunos literales Python y los comentarios no son extensiones que puedas añadir libremente a JSON. Una tupla puede convertirse en una lista después de guardar y cargar; las fechas y los objetos Decimal necesitan una política de conversión explícita.
La referencia oficial del módulo json describe qué valores admite y cómo se configuran la codificación y la decodificación.
Guardar un registro Unicode y leerlo de nuevo
El ejemplo utiliza café para mostrar un nombre con un carácter no ASCII. Reemplaza expenses-demo.json, por lo que debes trabajar en una carpeta desechable. Guarda el script como json_demo.py en UTF-8 y ejecuta python json_demo.py con el entorno del proyecto seleccionado. En macOS o Ubuntu, utiliza python3 fuera del entorno si corresponde.
import json
from pathlib import Path
data = {"currency": "KRW", "expenses": [{"name": "café", "amount": 8000}]}
path = Path("expenses-demo.json")
path.write_text(json.dumps(data, ensure_ascii=False, indent=2, allow_nan=False), encoding="utf-8")
loaded = json.loads(path.read_text(encoding="utf-8"))
amount = loaded["expenses"][0]["amount"]
if type(amount) is not int or amount < 0:
raise ValueError("invalid amount")
print(loaded["expenses"][0]["name"])
print(amount)
La salida esperada es:
café
8000
Abre el archivo generado para comprobar que contiene un objeto con una lista de gastos. El programa vuelve a leerlo, consulta el importe y valida su tipo y su rango antes de mostrar el resultado.
Distinguir análisis del formato y validación
Que un JSON se interprete correctamente no demuestra que contenga las claves obligatorias, las colecciones, los tipos y los rangos que exige la aplicación. El ejemplo utiliza type(amount) is int para excluir booleanos, porque bool es una subclase de int. isinstance() puede ser apropiado si deseas admitir subclases; el contrato determina la comprobación.
| Función | Operación |
|---|---|
| load(archivo) | Archivo → objeto Python |
| loads(texto) | Cadena → objeto Python |
| dump(objeto, archivo) | Objeto Python → archivo |
| dumps(objeto) | Objeto Python → cadena JSON |
dumps() devuelve texto: no crea un archivo por sí misma. Además, allow_nan=False rechaza constantes numéricas no estándar al serializar. No convierte automáticamente toda lectura posterior en una validación estricta de entradas externas; también necesitas reglas para constantes no estándar y claves repetidas.
Separar representación de caracteres y codificación
ensure_ascii=False conserva caracteres no ASCII legibles en el texto en lugar de sustituirlos por secuencias de escape. No elige la codificación del archivo: UTF-8 se configura por separado. La opción indent cambia la presentación sin cambiar el significado de los datos.
Un JSON mal formado produce JSONDecodeError. Corrige las comillas o la coma final incorrecta en lugar de utilizar eval(). En el objeto Python de origen, prueba los importes -1 y True, comprueba que la validación los rechaza y después restaura 8000.
Esta práctica presupone una estructura concreta. Un importador general también debe comprobar las claves y la forma de la lista que rodea al importe. Las solicitudes HTTP y las respuestas JSON aplican la misma distinción a datos recibidos de un servidor.




