Blog
Serialization Security Machine Learning

JSON vs Pickle: ¿Cuándo usar cada uno y por qué importa?

Una comparación práctica y profesional entre JSON y Pickle para serializar datos en Python, con ejemplos, ventajas, riesgos y recomendaciones claras.

Raul Mauricio Uñate Castro Raul Mauricio Uñate Castro · 3 de junio de 2026
JSON vs Pickle: ¿Cuándo usar cada uno y por qué importa?

Introducción

Serializar datos es una tarea cotidiana en el desarrollo de software: guardar el estado de un objeto, intercambiar información entre servicios o persistir resultados de un modelo de machine learning. En Python, dos herramientas dominan este espacio: JSON y Pickle.

Aunque ambas sirven para convertir datos a un formato almacenable o transmisible, sus filosofías, capacidades y riesgos son radicalmente distintos. Elegir la incorrecta puede derivar en problemas de portabilidad, vulnerabilidades de seguridad o simplemente un código más difícil de mantener.

Este artículo analiza ambas opciones en profundidad para que puedas tomar la decisión correcta en cada contexto.

¿Qué es JSON?

JSON (JavaScript Object Notation) es un formato de texto ligero y legible por humanos, diseñado originalmente para intercambio de datos en la web. En Python, el módulo estándar json permite serializar y deserializar estructuras de datos nativas.

import json

data = {"nombre": "Ana", "edad": 30, "activo": True}

# Serializar a string
json_str = json.dumps(data)
print(json_str)  # '{"nombre": "Ana", "edad": 30, "activo": true}'

# Guardar en archivo
with open("datos.json", "w") as f:
    json.dump(data, f, indent=2)

# Leer desde archivo
with open("datos.json", "r") as f:
    cargado = json.load(f)

JSON soporta un conjunto limitado de tipos: str, int, float, bool, None, list y dict. Cualquier otro tipo requiere un serializador personalizado.

¿Qué es Pickle?

Pickle es el protocolo de serialización nativo de Python. A diferencia de JSON, no produce texto legible, sino un flujo de bytes binario capaz de representar prácticamente cualquier objeto de Python: clases personalizadas, funciones, closures, objetos de NumPy, modelos de scikit-learn, y más.

import pickle

class Punto:
    def __init__(self, x, y):
        self.x = x
        self.y = y

punto = Punto(3, 7)

# Serializar a bytes
datos_bytes = pickle.dumps(punto)

# Guardar en archivo
with open("punto.pkl", "wb") as f:
    pickle.dump(punto, f)

# Leer desde archivo
with open("punto.pkl", "rb") as f:
    cargado = pickle.load(f)

print(cargado.x, cargado.y)  # 3 7

Pickle es poderoso precisamente porque no tiene las restricciones de tipo que tiene JSON, pero ese poder tiene un precio.

Cuándo usar cada uno

Usa JSON cuando:

  • Necesitas interoperabilidad: el archivo o stream será consumido por otro lenguaje, sistema o API.
  • Los datos son configuraciones, respuestas de API o registros estructurados con tipos simples.
  • Quieres que el archivo sea legible e inspeccionable por humanos.
  • El entorno de producción prioriza la seguridad (ver más adelante).

Usa Pickle cuando:

  • Trabajas exclusivamente en un entorno Python y necesitas persistir objetos complejos.
  • Estás en un flujo de machine learning: guardar modelos entrenados, pipelines de transformación o resultados intermedios.
  • El rendimiento de serialización es crítico y los datos son grandes arreglos o estructuras anidadas complejas.
  • Necesitas preservar el estado completo de un objeto, incluyendo métodos y referencias.

Ventajas y desventajas

Criterio JSON Pickle
Legibilidad ✅ Texto plano ❌ Binario opaco
Tipos soportados ⚠️ Limitado ✅ Casi cualquier objeto Python
Interoperabilidad ✅ Universal ❌ Solo Python
Seguridad ✅ Seguro ⚠️ Riesgoso sin validación
Rendimiento (objetos grandes) ⚠️ Más lento ✅ Más rápido
Portabilidad entre versiones ✅ Alta ⚠️ Puede romperse entre versiones

Consideraciones de seguridad: el riesgo real de Pickle

Este es el punto más crítico y frecuentemente subestimado.

Pickle puede ejecutar código arbitrario durante la deserialización. Esto significa que cargar un archivo .pkl de una fuente no confiable es equivalente a ejecutar código desconocido en tu máquina.

# NUNCA hagas esto con archivos de origen desconocido:
with open("modelo_externo.pkl", "rb") as f:
    modelo = pickle.load(f)  # Riesgo de ejecución de código malicioso

Un atacante puede craftar un archivo Pickle que, al cargarse, ejecute comandos del sistema:

import pickle, os

class Payload:
    def __reduce__(self):
        return (os.system, ("whoami",))

# Esto ejecuta 'whoami' al deserializar
payload = pickle.dumps(Payload())
pickle.loads(payload)

Regla de oro: nunca deserialices con Pickle datos que no hayas generado y controlado tú mismo.

JSON, en cambio, solo define estructura de datos. No puede contener lógica ejecutable, lo que lo hace intrínsecamente seguro para procesar datos externos.

Rendimiento y portabilidad

Para objetos simples (dicts, listas), JSON y Pickle tienen un rendimiento comparable. La diferencia se vuelve notoria con objetos complejos o grandes volúmenes de datos.

import json, pickle, time

data = list(range(1_000_000))

# JSON
t0 = time.perf_counter()
json_bytes = json.dumps(data).encode()
print(f"JSON serializar: {time.perf_counter() - t0:.4f}s")

# Pickle
t0 = time.perf_counter()
pkl_bytes = pickle.dumps(data)
print(f"Pickle serializar: {time.perf_counter() - t0:.4f}s")

En general, Pickle es más rápido para objetos Python complejos, y los archivos resultantes suelen ser más compactos. Sin embargo, un archivo .pkl generado con Python 3.11 puede no cargarse correctamente en Python 3.8, o comportarse de forma distinta si la clase original fue modificada. JSON no tiene este problema: es un estándar abierto y estable.

Para escenarios de alto rendimiento con datos numéricos, considera alternativas como numpy.save, HDF5 o Apache Parquet, que ofrecen mejor rendimiento y portabilidad que Pickle.

Casos de uso reales

JSON es preferido por:

  • Equipos de backend que exponen APIs REST.
  • Proyectos que almacenan configuraciones (settings.json, .env estructurado).
  • Pipelines de datos que intercambian información entre Python, JavaScript, Java u otros lenguajes.
  • Logging estructurado en producción.

Pickle es preferido por:

  • Data scientists que persisten modelos de scikit-learn, XGBoost o LightGBM entre sesiones.
  • Flujos de MLOps donde los artefactos son objetos Python puros.
  • Caché de resultados computacionalmente costosos dentro de un sistema Python cerrado.
  • Frameworks como joblib (que extiende Pickle) para paralelismo eficiente.

Recomendaciones y buenas prácticas

  1. Por defecto, elige JSON. Es seguro, portable e interoperable. Si tus datos caben en sus tipos soportados, no hay razón para usar Pickle.

  2. Usa Pickle solo en entornos controlados. Nunca cargues archivos .pkl de fuentes externas, usuarios o redes públicas.

  3. Para modelos de ML, considera joblib o formatos específicos. Frameworks como scikit-learn tienen soporte nativo para joblib, que es más eficiente que Pickle puro. Para redes neuronales, usa los formatos propios (torch.save, model.save en Keras).

  4. Si necesitas serializar objetos Python complejos de forma segura, evalúa alternativas como marshmallow, pydantic o msgpack, que ofrecen validación y mayor control.

  5. Documenta el protocolo de Pickle usado. Si compartes archivos .pkl entre versiones de Python, especifica explícitamente el protocolo:

# Protocolo 4 es compatible con Python 3.4+
pickle.dump(obj, f, protocol=4)
  1. Versiona tus clases si usas Pickle a largo plazo. Un cambio en la definición de una clase puede hacer que archivos .pkl antiguos sean incompatibles o carguen objetos en estado inconsistente.

Conclusión

JSON y Pickle no son competidores directos: son herramientas con propósitos distintos. JSON brilla en la interoperabilidad, la seguridad y la legibilidad; Pickle destaca cuando necesitas persistir objetos Python complejos dentro de un ecosistema controlado.

La elección correcta casi siempre es JSON si tienes alguna duda. Recurre a Pickle cuando tengas una necesidad concreta que JSON no puede satisfacer, y hazlo con plena conciencia de las implicaciones de seguridad.

Conocer las diferencias entre ambas herramientas —y saber cuándo aplicar cada una— es una señal clara de madurez como desarrollador Python.