Python JSON: Codificación, decodificación y manejo de archivos – Guía práctica
Python JSON: Codificación, decodificación y manejo de archivos – Guía práctica
¿Qué es JSON en Python?
JSON —abreviatura de JavaScript Object Notation— es el formato de intercambio de datos basado en texto más utilizado. En Python se mapea directamente a estructuras de datos nativas: los objetos se convierten en dicts, los arrays en lists, strings, números, booleanos y null se traducen a str, int/float, bool y None respectivamente. El módulo json de la biblioteca estándar maneja todas las conversiones.
Librería JSON en Python
Importa el módulo una vez en tu script:
import json
El módulo ofrece cuatro métodos principales:
| Método | Descripción |
|---|---|
| dumps() | Convertir un objeto Python a cadena JSON. |
| dump() | Escribir una cadena JSON directamente a un objeto archivo. |
| loads() | Analizar una cadena JSON a objeto Python. |
| load() | Leer y analizar un archivo JSON a objeto Python. |
Python a JSON (Codificación)
La codificación es el proceso de convertir tipos de datos de Python a JSON. El mapeo por defecto se muestra a continuación:
| Python | JSON |
|---|---|
| dict | Object |
| list | Array |
| str/unicode | String |
| int/long | Number (int) |
| float | Number (real) |
| True | true |
| False | false |
| None | null |
Ejemplo usando json.dumps():
import json
x = {
"nombre": "Ken",
"edad": 45,
"casado": True,
"hijos": ("Alice", "Bob"),
"mascotas": ["Perro"],
"coches": [
{"modelo": "Audi A1", "mpg": 15.1},
{"modelo": "Zeep Compass", "mpg": 18.1}
]
}
# Impresión bonita con claves ordenadas
cadena_ordenada = json.dumps(x, indent=4, sort_keys=True)
print(cadena_ordenada)
Salida:
{
"edad": 45,
"coches": [
{ "modelo": "Audi A1", "mpg": 15.1 },
{ "modelo": "Zeep Compass", "mpg": 18.1 }
],
"hijos": [ "Alice", "Bob" ],
"casado": true,
"nombre": "Ken",
"mascotas": [ "Perro" ]
}
Escribir un objeto JSON a un archivo es directo con json.dump():
with open('archivo_json.json', 'w') as archivo_escritura:
json.dump(x, archivo_escritura, indent=4, sort_keys=True)
Tras ejecutar el script, archivo_json.json contendrá los datos serializados.
JSON a Python (Decodificación)
La decodificación invierte el mapeo, convirtiendo una cadena o archivo JSON de vuelta a objetos Python nativos. La tabla de conversión refleja la tabla de codificación:
| JSON | Python |
|---|---|
| Object | dict |
| Array | list |
| String | str |
| Number (int) | int |
| Number (real) | float |
| true | True |
| false | False |
| null | None |
Ejemplo usando json.loads():
import json
datos_persona = '{"persona": {"nombre": "Kenn", "sexo": "masculino", "edad": 28}}'
obj = json.loads(datos_persona)
print(obj)
print(type(obj))
print(obj.get('persona'))
Salida:
{'persona': {'nombre': 'Kenn', 'sexo': 'masculino', 'edad': 28}}
<class 'dict'>
{'nombre': 'Kenn', 'sexo': 'masculino', 'edad': 28}
Leer un archivo JSON directamente:
with open('archivo_json.json') as f:
datos = json.load(f)
print(datos)
Salida:
{'nombre': 'Ken', 'edad': 45, ...}
Codificación compacta y pretty-print
Para transmisión en red, la codificación compacta elimina espacios en blanco:
lst = ['a', 'b', 'c', {"4": 5, "6": 7}]
compacta = json.dumps(lst, separators=(',', ':'))
print(compacta)
Salida:
["a","b","c",{"4":5,"6":7}]
Para legibilidad humana, pretty-printing usa indentación:
dic = {"a": 4, "b": 5}
bonita = json.dumps(dic, indent=4, separators=(',', ': '))
print(bonita)
Salida:
{
"a": 4,
"b": 5
}
Codificación de objetos complejos
El módulo json no puede serializar objetos arbitrarios. Para manejar un número complex, proporciona una función default:
def codificar_complejo(o):
if isinstance(o, complex):
return [o.real, o.imag]
raise TypeError(f"{repr(o)} no es serializable JSON")
print(json.dumps(4 + 5j, default=codificar_complejo))
Salida:
[4.0, 5.0]
Decodificación de objetos complejos
Usa object_hook para detectar un marcador personalizado y reconstruir el número complejo:
def es_complejo(obj):
if "__complex__" in obj:
return complex(obj["real"], obj["img"])
return obj
complejo_obj = json.loads('{"__complex__": true, "real": 4, "img": 5}', object_hook=es_complejo)
print(complejo_obj)
Salida:
(4+5j)
Clases de serialización y deserialización
Las clases JSONEncoder y JSONDecoder proporcionan control granular:
JSONEncoder.default(o)– sobrescribir para serializar objetos personalizados.JSONEncoder.encode(o)– devolver cadena JSON.JSONEncoder.iterencode(o)– iterar sobre la cadena de salida.JSONDecoder.decode(s)– analizar cadena JSON.JSONDecoder.raw_decode(s)– analizar desde un índice dado.
Ejemplo:
from json.encoder import JSONEncoder
print(JSONEncoder().encode({"color": ["rojo", "amarillo", "verde"]}))
Obtener JSON desde una URL
Usando requests para descargar un feed JSON en vivo (ej. CityBike NYC):
import json, requests
response = requests.get("https://feeds.citibikenyc.com/stations/stations.json")
bike_dict = json.loads(response.text)
print(bike_dict['stationBeanList'][0])
Salida:
{ 'id': 487, 'stationName': 'E 20 St & FDR Drive', 'availableDocks': 24, ... }
Manejo de excepciones JSON
La excepción principal es json.JSONDecodeError, subclase de ValueError. Ejemplo de manejo:
try:
with open('malo.json') as f:
datos = json.load(f)
except json.JSONDecodeError as e:
print(f"JSON inválido: {e}")
Valores numéricos especiales
RFC 8259 no permite Infinity o NaN, pero el codificador de Python los representa como cadenas:
print(json.dumps(float('inf')))
print(json.dumps(float('nan')))
Salida:
Infinity NaN
Claves repetidas en JSON
Cuando una clave aparece múltiples veces, json.loads() de Python mantiene solo la última ocurrencia:
json.loads('{"a": 1, "a": 2, "a": 3}') # -> {'a': 3}
Herramientas de línea de comandos
El módulo json.tool formatea y valida JSON desde la línea de comandos:
$ echo '{"nombre": "Rey Arturo"}' | python3 -m json.tool
{
"nombre": "Rey Arturo"
}
Ventajas de JSON en Python
- Soporte nativo vía módulo
json. - Legible por humanos con pretty-printing.
- Ampliamente adoptado para APIs, configuración y almacenamiento de datos.
- Independiente de lenguaje y ligero.
Limitaciones
- No soporta tipos de datos personalizados sin codificador personalizado.
- Límite de profundidad de recursión máxima limita estructuras profundamente anidadas.
- Documentos grandes pueden ser intensivos en memoria al cargarse completamente.
Chuleta de Python JSON
| Función | Descripción |
|---|---|
| json.dumps(obj) | Serializar objeto Python a cadena JSON. |
| json.dump(obj, archivo) | Escribir cadena JSON a un archivo. |
| json.dumps(obj, separators=(",", ":")) | Representación compacta sin espacios. |
| json.dumps(obj, indent=4) | JSON pretty-printed con indentación. |
| json.dumps(obj, sort_keys=True) | Ordenar claves de diccionario alfabéticamente. |
| json.dumps(obj, default=personalizado) | Codificar objetos no soportados. |
| JSONEncoder().encode(obj) | Serialización manual vía clase encoder. |
| json.loads(s) | Analizar cadena JSON a objeto Python. |
| json.loads(s, object_hook=personalizado) | Deserialización personalizada. |
| JSONDecoder().decode(s) | Deserialización manual vía clase decoder. |
python
- Dominando tipos de datos en Python: Guía práctica
- Dominando operadores en Python: Guía completa
- Dominando el bucle while en Python: Sintaxis, ejemplos y mejores prácticas
- Dominando la sentencia pass en Python: Guía práctica
- Dominando funciones en Python: Sintaxis, tipos y ejemplos prácticos
- Dominando argumentos de funciones en Python: Posicionales, por palabra clave y por defecto
- Dominando Diccionarios en Python: Creación, Manipulación y Técnicas Avanzadas
- Entrada/Salida de Archivos en Python: Dominando Operaciones de Lectura, Escritura y Gestión
- Comprobación de existencia de archivos y directorios en Python – Guía práctica
- Entrada/Salida de Archivos en Python: Domina las Operaciones I/O
- Lectura de archivos en Java con BufferedReader – Guía práctica con ejemplos