Validar el JSON de una IA con Python: del formato a los datos comprobables
Una respuesta de IA puede parecer ordenada y seguir siendo inservible para tu automatización. Que un texto se convierta en un objeto JSON no demuestra que tenga los campos esperados, que sus valores sean admisibles ni que coincida con el documento original. La solución práctica es separar esas comprobaciones antes de guardar o ejecutar nada.
Vamos a construir un filtro pequeño con la biblioteca estándar de Python para clasificar documentos ficticios. Se ha ejecutado localmente con datos sintéticos; no se ha llamado a un modelo, conectado una cuenta ni desplegado una integración. El objetivo es que puedas reproducir el control y entender dónde deja de protegerte.
Define un contrato antes de pedir la respuesta
En este ejemplo, cada documento debe producir exactamente tres campos: documento_id, un texto no vacío; paginas, un entero entre 1 y 100; y categoria, con el valor manual o informe. Son reglas elegidas para la demostración, no límites de ninguna plataforma.
{"documento_id":"DOC-01","paginas":2,"categoria":"manual"}
El contrato excluye campos adicionales. Si aparece una propiedad como accion, no se interpreta como una orden ni se ejecuta: el registro se rechaza. Tampoco convertimos automáticamente el texto "2" en el número 2; preferimos que la discrepancia sea visible.
Si trabajas con JSON Schema, las propiedades obligatorias se declaran mediante required y las adicionales se pueden limitar con additionalProperties. El código siguiente no implementa ese estándar: es un filtro específico para este contrato, deliberadamente corto y sin paquetes externos.
Un validador reproducible, sin permisos sobre otros sistemas
Guarda este bloque como validar_json.py. La función devuelve el objeto aceptado o lanza una excepción; no crea archivos, envía mensajes ni modifica bases de datos.
"""Ejemplo didáctico: valida registros sintéticos, sin API ni escrituras."""
import json
def sin_repetidas(pares):
objeto = {}
for clave, valor in pares:
if clave in objeto:
raise ValueError("Clave repetida")
objeto[clave] = valor
return objeto
def sin_constantes(valor):
raise ValueError("Constante no permitida")
def validar(texto):
if not isinstance(texto, str) or len(texto.encode("utf-8")) > 4096:
raise ValueError("Entrada no admitida")
dato = json.loads(texto, object_pairs_hook=sin_repetidas,
parse_constant=sin_constantes)
if type(dato) is not dict:
raise ValueError("Se esperaba un objeto")
if set(dato) != {"documento_id", "paginas", "categoria"}:
raise ValueError("Campos distintos del contrato")
if type(dato["documento_id"]) is not str or not dato["documento_id"].strip():
raise ValueError("Identificador vacío o de tipo incorrecto")
if type(dato["paginas"]) is not int or not 1 <= dato["paginas"] <= 100:
raise ValueError("Páginas fuera de contrato")
if type(dato["categoria"]) is not str or dato["categoria"] not in {"manual", "informe"}:
raise ValueError("Categoría no admitida")
return dato
Hay dos detalles importantes. El decodificador de Python acepta por defecto nombres repetidos, conservando el último valor, y constantes como NaN; aquí las rechazamos de forma explícita. Además, usamos type(... ) is int para no aceptar un booleano como número de páginas. El contrato también rechaza 2.0: no debe confundirse con JSON Schema, donde un número sin parte fraccionaria puede satisfacer el tipo integer.
El límite de 4096 bytes se comprueba sobre el texto recibido. No protege una descarga anterior ilimitada ni sustituye límites de tiempo, tamaño o profundidad en una aplicación real. No alimentes este ejemplo directamente con entradas arbitrarias de Internet y permisos de escritura.
Cómo probarlo en tu equipo
Añade estas líneas al final del archivo y ejecuta python validar_json.py. Solo procesan el ejemplo incluido.
ejemplo = '{"documento_id":"DOC-01","paginas":2,"categoria":"manual"}'
print(validar(ejemplo))
La ejecución local para esta pieza se realizó con Python 3.14.9. La batería de 14 casos cumplió todas las expectativas: aceptó el registro normal y rechazó el JSON roto, una lista, campos ausentes o extra, un número escrito como texto, un booleano, páginas fuera de rango, una categoría distinta, un identificador vacío, claves repetidas, NaN, una entrada demasiado grande y un número decimal.
Estos resultados verifican esa batería del filtro, no la fiabilidad de un modelo de IA. Los casos se escribieron expresamente para la prueba: no son respuestas capturadas de un asistente ni una medición de precisión en documentos reales.
La prueba que demuestra el límite: un dato falso también pasa
En una comprobación adicional, la referencia sintética decía que el documento tenía dos páginas. Se entregó al filtro el mismo registro con tres páginas. El filtro lo aceptó, porque tres cumple el tipo y el rango establecidos. El dato era incorrecto respecto a la referencia, aunque el contrato se cumplía.
Por eso necesitas una segunda comparación con la fuente. En una aplicación documental, comprueba que el identificador corresponde al archivo realmente procesado y contrasta el número de páginas con un lector del documento. Si clasificas su contenido, conserva un fragmento o una localización que permita revisar la propuesta de categoría; una cita generada también debe comprobarse.
Un identificador no vacío no acredita que exista en tu sistema, y una categoría permitida no acredita que sea la correcta. La decisión de aceptar, pedir revisión o detener debe depender de esas comprobaciones, no de que el JSON resulte fácil de leer.
Del ensayo local a una automatización controlada
Empieza con archivos de prueba sin datos personales. Ante un error, conserva el motivo de forma proporcionada y detén el paso de escritura; no reintentes indefinidamente ni ejecutes instrucciones encontradas dentro del documento. Cuando el registro supere formato, contrato y contraste con la fuente, todavía quedará comprobar si existe autorización para la operación siguiente.
En CódigoIA explicamos esta última diferencia en qué pruebas pedir cuando un agente dice «hecho». Este filtro resuelve una parte concreta: impedir que ciertas respuestas mal formadas o fuera de contrato lleguen al siguiente paso. No autentica documentos, verifica hechos por sí solo ni convierte una respuesta estructurada en permiso para actuar.
Fuentes consultadas
- Documentación oficial de Python: json, decodificación, nombres repetidos, constantes y cautelas con entradas no fiables.
- JSON Schema: objetos, propiedades obligatorias y adicionales.
- JSON Schema: tipos numéricos, significado de integer.
Documentación consultada el 14 de noviembre de 2026. Los límites y decisiones del filtro pertenecen a este ejemplo, no a una promesa de compatibilidad con todas las aplicaciones.
Contenido elaborado con asistencia de inteligencia artificial a partir de las fuentes indicadas.
Descubre más desde Código IA
Suscríbete y recibe las últimas entradas en tu correo electrónico.