# JSON es la caverna de Platón

> Un validador de JSON responde a una sola pregunta: ¿está bien formado? Durante veinte años tratamos esa respuesta como si significara 'el dato es correcto'. Con un humano en cada extremo colaba. Sin él, no.

- Fuente canónica: https://www.ricardovelit.com/blog/p/json-es-la-caverna-de-platon
- Nivel: principiante · Lectura: 5 min · Publicado: 2026-09-09
- Etiquetas: json, epistemologia, agentes, datos
- Relacionados: [lambda-data-datos-con-estado-epistemico](https://www.ricardovelit.com/blog/p/lambda-data-datos-con-estado-epistemico.md), [en-defensa-de-json](https://www.ricardovelit.com/blog/p/en-defensa-de-json.md)
- Contiene componentes interactivos que solo funcionan en la versión web.

---
## La provocación

Un validador de JSON es, probablemente, el test más inútil de tu pipeline: pasa en verde
con especial entusiasmo justo cuando el dato está mal.

Comprueba una cosa —que las llaves cierren, que las comas estén donde toca, que las
comillas emparejen— y sin embargo, en casi todas las arquitecturas que he visto, ese
`200 OK` con JSON válido se trata como si significara *el dato es correcto*. No lo
significa. Nunca lo significó.

## Las sombras en la pared

En el mito de la caverna, unos prisioneros ven sombras proyectadas en un muro y toman las
sombras por las cosas. No están equivocados sobre lo que ven: la sombra existe, es nítida,
es reproducible, dos prisioneros distintos ven la misma. Están equivocados sobre lo que
**es**.

Mira esta sombra:

```json
{ "valor": 100 }
```

Es JSON válido. ¿100 qué? ¿Euros, pesos, miligramos, un porcentaje, grados, unidades en
stock, milisegundos? El formato no lo sabe. El validador dice que sí. El esquema, si lo
tienes, dice `number`, que es exactamente la misma sombra con el contorno más marcado.

Añade contexto y el problema no desaparece: se disfraza.

```json
{ "fecha": "01/02/2026", "importe": 1500, "cliente": "Acme" }
```

¿1 de febrero o 2 de enero? ¿1500 con IVA o sin? ¿`"Acme"` es un nombre para mostrar o una
clave foránea? Todo esto es válido. Todo esto es ambiguo. Y la ambigüedad no está en tu
código: está en el formato.

## Por qué esto no dolía antes

Porque siempre hubo alguien fuera de la caverna.

El significado nunca viajó dentro del JSON. Viajaba en la documentación, en el Confluence,
en el hilo de Slack donde preguntaste "oye, ¿la fecha es ISO o europea?" y alguien te
contestó. JSON transportaba una forma lo bastante regular como para que **una persona en
cada extremo inyectara el significado a mano**.

Funcionaba, y era barato. Pero conviene ver lo que era en realidad: un sistema de dos
piezas, el formato y el humano. Y hemos quitado el humano.

## Qué pasa cuando el que lee es un modelo

Un LLM que recibe `{"fecha": "01/02/2026"}` no tiene Confluence, ni Slack, ni al compañero
que lleva seis años en el proyecto. Tiene el nombre de la clave y una distribución de
probabilidad. Así que **infiere**. Y esa inferencia sale por el otro lado con el mismo
aplomo con el que saldría un dato medido, porque a la salida hay otro JSON, y otro JSON
tampoco tiene sitio donde decir "esto me lo estoy inventando a medias".

Ese es el mecanismo de buena parte de lo que llamamos alucinación. No es que el modelo
mienta: es que **el formato le exige comprometerse**. Si un agente está un 20 % seguro de
la dirección de un cliente, JSON le obliga a serializarla como una cadena absoluta. La
duda existía antes de `JSON.stringify` y no existe después. La certeza no se pierde por el
camino: se destruye en la serialización.

## "Para eso están los esquemas"

Es la objeción obvia, y es la que menos aguanta.

JSON Schema, OpenAPI, Zod, Pydantic: todos hacen la misma cosa, que es **restringir la
sintaxis con más precisión**. `z.number()` no dice euros. `z.number().describe("euros")` es
un comentario para humanos: no se propaga cuando sumas, no se comprueba en la frontera
siguiente, no impide sumar euros con pesos y obtener un número perfectamente válido.

| Lo que el esquema garantiza | Lo que necesitabas saber |
| --- | --- |
| Es un número | Es dinero, en una moneda concreta, y no se puede sumar con otra |
| Es una cadena con formato fecha | Es un instante, en una zona horaria, y hasta cuándo sigue siendo cierto |
| El campo está presente | El dato se midió, se dedujo, o se lo inventó alguien |
| Cumple el contrato | El emisor estaba seguro de él |

Un esquema es la sombra dibujada con más detalle. Sigue siendo una sombra.

## Las tres cosas que JSON estructuralmente no puede llevar

1. **Ontología.** Qué clase de cosa es esto. `string` e `int32` son categorías de memoria,
   no del mundo. `Moneda`, `Medida`, `Instante` sí lo son, y ninguna cabe en JSON salvo
   como acuerdo verbal entre dos equipos.
2. **Certeza y procedencia.** Cuánto se lo cree quien lo envía, y de dónde salió. Un valor
   medido por un sensor y otro completado por un modelo son indistinguibles una vez
   serializados.
3. **Validez temporal.** Hasta cuándo sigue siendo verdad. "El CEO de Acme es Ana" *fue*
   cierto. La verdad caduca; el campo, no.

Puedes añadir claves: `"confidence": 0.2`, `"source": "sensor_3"`, `"valid_until": "…"`.
Hazlo, es mejor que nada. Pero mira bien lo que has construido: una convención que **nada
obliga a leer**. El siguiente servicio de la cadena puede ignorarla entera y seguir siendo
perfectamente conforme al contrato. No es física, es decoración.

## Donde más se nota: las cadenas de agentes

Un agente llama a otro, que llama a una herramienta, que devuelve un JSON que alimenta a un
tercero. Cuatro saltos. En el salto 1 alguien estaba un 70 % seguro. En el salto 4 esa
cifra es un `number` en un campo, y nadie recuerda —porque no hay dónde recordarlo— si
salió de un sensor calibrado, de una base de datos, o de un modelo que la produjo por
completar la frase.

El sistema no falla ruidosamente. Falla **en verde**, con todos los contratos cumplidos y
todos los tests pasando.

## La conclusión incómoda

JSON no está roto. Hace exactamente aquello para lo que se diseñó, y lo hace muy bien:
mover estructura de A a B sin opinar sobre su significado. Eso viene de lejos: en 1948
Shannon fundó la teoría de la información diciendo con toda intención que los aspectos
semánticos de la comunicación eran irrelevantes para el problema de ingeniería. Tenía
razón. Para un cable.

El problema no es el formato. El problema es que montamos encima de él un sistema
cognitivo y **quitamos la pieza que ponía el significado** sin sustituirla por nada.

Salir de la caverna no consiste en validar mejor. Consiste en que el dato lleve encima su
tipo ontológico, su certeza, su procedencia y su caducidad, y en que el runtime esté
obligado a respetarlos. Eso es exactamente lo que propone
[ΛD](/p/lambda-data-datos-con-estado-epistemico).

Y porque una tesis que nadie ataca es solo un eslogan, escribí también
[la mejor defensa que se me ocurre de lo contrario](/p/en-defensa-de-json).

## Para llevarte

- "JSON válido" contesta una pregunta sintáctica y ninguna semántica.
- Durante veinte años bastó porque había un humano en cada extremo poniendo el significado.
- Ese humano ya no está, y el modelo que lo sustituye rellena el hueco adivinando.
- Los esquemas afinan el contorno de la sombra. No la convierten en el objeto.
