Un tutorial detalla la construcción, en Python, de un proceso de serialización JSON capaz de manejar tipos de datos personalizados, tolerar datos malformados y adaptarse a la evolución de los esquemas. El objetivo es hacer circular conjuntos de datos entre archivos, procesos, microservicios y API sin que la canalización se interrumpa ante la primera anomalía.
- Un tutorial muestra cómo serializar tipos personalizados en Python con JSON.
- Un codificador añade la clave «__type__» para conservar la naturaleza original de los objetos.
- Un decodificador tolerante registra advertencias y devuelve el valor bruto ante datos malformados.
- Una función fábrica aplica valores por defecto y adapta la carga a la evolución de los esquemas.
Según el artículo, solo una pequeña parte del tiempo de un ingeniero en aprendizaje automático se dedica a escribir la arquitectura del modelo. El resto corresponde a la plomería de datos (« data plumbing »), es decir, la limpieza, el preprocesamiento y la transformación de los datos. Una parte de este trabajo consiste en serializar los datos, convertirlos en texto para almacenarlos o transmitirlos, y luego deserializarlos, es decir, reconstruirlos como objetos Python.
El problema inicial se debe a las limitaciones del formato JSON, que solo reconoce algunos tipos básicos. Un diccionario de configuración de experimento que contiene un Enum, un set, un Path o un datetime provoca un error al llamar a json.dumps(), con el mensaje « TypeError: Object of type ModelType is not JSON serializable ».
Un codificador personalizado
El primer paso consiste en definir una clase que herede de json.JSONEncoder y redefina su método default(). Para cada tipo problemático, una condición del tipo isinstance() indica la conversión a realizar. Los datetime se transforman en un diccionario que contiene un valor en formato ISO, los set en listas, los Path en cadenas de caracteres y los Enum en su valor.
Un detalle juega un papel central: el codificador añade una clave « __type__ » a los objetos que pueden perder su naturaleza original, como un set convertido en lista. Una vez pasado a json.dumps() mediante el argumento cls, el diccionario de ejemplo se serializa sin error, y el datetime aparece en la forma « 2026-09-28T14:26:10.328310 ».
Un decodificador tolerante a los errores
En sentido inverso, la función robust_decoder se pasa a json.loads() mediante el argumento object_hook. Se llama en cada diccionario anidado y reconstruye el objeto original cuando la clave « __type__ » está presente. Las conversiones se colocan en un bloque try, que intercepta los errores ValueError y TypeError.
En caso de datos malformados, la función registra una advertencia mediante el módulo logging y devuelve el valor bruto, sin interrumpir el proceso. El artículo indica que este comportamiento puede ser reemplazado por un valor de respaldo o un diccionario de error específico. Tras la deserialización, la fecha se reconoce correctamente como un datetime y la lista como un set.
Gestionar la evolución de los esquemas
Los esquemas de metadatos de los modelos cambian con frecuencia: se añaden hiperparámetros, se abandonan otros, algunas métricas se renombran. Para responder a ello, el autor propone una función fábrica, load_experiment_config(), que carga el JSON con el decodificador y luego aplica valores por defecto mediante get().
El ejemplo se centra en un hiperparámetro « learning_rate » ausente en la configuración anterior, al que se asigna el valor por defecto 0.001. El mismo principio puede aplicarse a cualquier nuevo parámetro. El artículo también menciona la posibilidad de eliminar los campos obsoletos durante la carga. Aplicado a la configuración original, la carga devuelve los tipos esperados: un entero para el identificador, un set para las variables, un PosixPath para la ruta, un datetime para la marca temporal y un float para la tasa de aprendizaje.
