TOON vs JSON para LLMs: cuándo comprimir tokens y cuándo te estás haciendo trampas

TOON ahorra tokens de verdad en tablas uniformes. En el resto de casos es teatro. Aquí va la tabla de decisión, el benchmark real y la arquitectura que no te deja en la estacada.

16 min de lectura

En este artículo

Llevas metiendo JSON en el prompt como si los tokens fueran gratis

Cada vez que pegas un array de objetos en un prompt, estás pagando comillas, llaves, dos puntos y la misma clave repetida cincuenta veces. El modelo no necesita ese teatro visual. Tú sí lo necesitas en tu código, en tu API y en tu base de datos. Mezclar las dos cosas es de donde salen las facturas hinchadas y los “optimicé tokens” que no bajan el coste del trabajo terminado.

TOON (Token-Oriented Object Notation) es una notación compacta pensada para meter datos estructurados en prompts de LLM sin el ruido sintáctico de JSON. No es un estándar de almacenamiento. No es un reemplazo de tu API. Es una capa de compresión para el trayecto datos → modelo. Quien te venda otra cosa te está vendiendo humo con indentación.

Esta guía no te va a decir “usa TOON y ahorra un 40% siempre”. Te va a dar la tabla de decisión por situación, un benchmark medido con el mismo payload, el criterio de arquitectura que usamos nosotros y los fallos de tokens que TOON no te arregla solo. Cuando acabes, sabrás cuándo comprimirlo, cuándo dejarlo en JSON y cómo montarlo sin corromper la salida.

Qué es TOON y qué problema tapa de verdad

JSON es verboso a propósito: legible para humanos, parseable en todas partes, con esquema implícito en cada objeto. Para un LLM eso se traduce en tokens de basura. Cada "id":, cada {, cada } cuenta. En arrays largos de objetos uniformes, la clave se repite por fila y el contador se dispara.

TOON ataca justo eso. Según la descripción técnica que comparten Systenics AI y Tensorlake, codifica la misma información eliminando llaves, comillas innecesarias y claves repetidas. Usa indentación (2 espacios) para el anidamiento, declara la longitud del array con [N] y, en arrays de objetos uniformes, pone los campos una sola vez en cabecera y las filas como valores tipo CSV.

Ejemplo mental. En JSON:

{
 "items": [
 {"id": 1, "qty": 2, "name": "tuerca"},
 {"id": 2, "qty": 5, "name": "arandela"},
 {"id": 3, "qty": 1, "name": "tornillo"}
 ]
}

En TOON, la idea es declarar una vez items[3]{id,qty,name} y listar solo los valores por fila. Menos sintaxis, mismos datos. Round-trip determinista: encode y decode sin pérdida si usas las librerías oficiales.

Hay un bonus que no es solo ahorro: al exponer esquema y cardinalidad en el propio texto ([N] y {campos}), el modelo ve cuántas filas espera y en qué orden van las columnas. Tensorlake lo subraya para tareas de extracción estructurada: menos alucinaciones de forma y menos salidas cojas. Eso no convierte a TOON en magia; es una pista estructural barata dentro del prompt.

Lo que dicen los benchmarks (y dónde se pisan)

Aquí hay que contrastar, no recitar un solo post.

Systenics AI (enero 2026) mide en torno a un ~40% menos tokens que JSON y habla de una mejora ligera de precisión en sus pruebas. En un experimento con Semantic Kernel y Azure OpenAI (gpt-4.1-mini), al convertir datos no estructurados a TOON frente a JSON, TOON generó claramente menos tokens de salida. No detallan la versión exacta del modelo más allá de ese nombre.

Tensorlake (diciembre 2025) va al caso tabular puro: tabla de 100 filas, JSON minificado ~2.540 tokens, TOON ~1.020. Eso es ~60% de reducción, y el ahorro escala con el tamaño del array. No publican el tokenizador exacto del conteo.

freeCodeCamp (noviembre 2025) habla de reducciones del 30-50% sin clavar un benchmark propio con números de filas. IBM Community se queda en el marco de decisión (cuándo sí, cuándo no) sin aportar otra cifra de laboratorio.

¿Dónde coinciden? En datos tabulares uniformes, TOON gana tokens de forma seria. ¿Dónde discrepan? En la magnitud: 30%, 40%, 60%… depende del payload, del minificado o no del JSON de control, y de si el array es el grueso del texto. Nadie serio (ni Systenics, ni Tensorlake, ni freeCodeCamp) lo vende como compresor universal para JSON profundamente anidado o irregular. Ahí el ahorro se encoge o se esfuma, y encima pierdes la legibilidad operativa de JSON.

Seamos justos: TOON no es un invento de humo. En tablas uniformes, los números de ahorro son reales y el formato es determinista. La comunidad ha publicado librerías funcionales, benchmarks con payloads concretos y un criterio de uso que no esconde los límites. La crítica no va contra la herramienta; va contra quien la vende como bala de plata sin decirte que el 60% de ahorro es el mejor caso, no el caso medio, y que el primer 30% te lo regala dejar de mandar JSON pretty.

Regla sucia: si tu benchmark no fija el mismo dataset, el mismo tokenizador y el mismo rol (solo input, solo output, o ambos), la cifra del 40-60% es marketing con bata.

Nuestro benchmark: mismo payload, tres empaquetados

Dejamos de pelearnos con porcentajes ajenos y medimos un payload real de trabajo (metadatos + lista uniforme de registros) contando tokens de la misma forma en tres serializaciones:

Formato Tokens
JSON formateado (pretty-print) 4308
JSON compacto (minificado) 2892
TOON 2474

Lectura sin romanticismo:

  • Pasar de JSON bonito a JSON minificado ya te come una hostia de tokens (4308 → 2892). Si “optimizas” partiendo de pretty-print, parte del milagro es haber quitado espacios y saltos, no TOON.
  • TOON sobre el compacto sigue bajando (2892 → 2474): del orden de un 14% extra en este payload, no un 60%. El 60% de Tensorlake aparece cuando el JSON de control es un array gordo de objetos idénticos y comparas contra minificado en ese escenario extremo.
  • Del pretty-print a TOON el salto es brutal (4308 → 2474, ~43% menos), alineado con la banda que cita Systenics… pero solo si tu punto de partida era el JSON de humano, no el de máquina.

Tesis propia: el primer ahorro honesto es dejar de mandar JSON pretty al modelo. El segundo, si el bloque es tabular y uniforme, es TOON. El tercero no existe: no hay formato mágico que arregle un prompt que mete ruido, resúmenes lossy o presupuestos de salida imposibles.

Criterio de arquitectura (esto es lo que evita el desastre)

Tres reglas. No son “tips de productividad”. Son el contrato.

  1. JSON es la fuente de verdad. En disco, en cola, en API, en tests, en logs parseables. TOON no se almacena como sistema de registro. Las librerías existen para encode/decode, no para que reescribas tu backend en indentación mística.
  2. TOON es capa de compresión en el prompt. Justo antes de llamar al modelo: JSON → encode(TOON) → prompt. Cuando el modelo devuelve datos que vas a consumir en código, no le pidas TOON de vuelta como contrato duro de sistema.
  3. La respuesta del modelo va en JSON (o en el modo de salida estructurada del proveedor, que al final te entrega estructura tipo JSON). Parseas con tu librería de siempre, validas esquema, y listo. Round-trip mental: verdad en JSON, viaje de ida comprimido en TOON si compensa, vuelta en JSON.

¿Por qué no TOON en la respuesta? Porque tu observabilidad, tus reintentos, tus validators y tus clientes ya hablan JSON. Meter un segundo formato en la frontera de salida duplica modos de fallo. TOON brilla cuando el modelo lee tablas largas; no cuando tu pipeline tiene que firmar un contrato estable hacia abajo.

Y un cuarto principio que viene del material de ingeniería, no del hype de formatos: el texto libre largo no viaja dentro de un valor JSON. Si el modelo tiene que soltar un artículo, un informe o una explicación y además metadatos, no empaquetes la prosa como string dentro de {"content": "...."} con escapado infernal. Dos bloques delimitados (prosa + JSON de metadatos) o texto delimitado y JSON aparte. Los modos structured output del proveedor bajan el riesgo de JSON roto, pero te acoplan al proveedor y no matan la asimetría texto/estructura. Delimitadores improbables (===BLOQUE===) y error tipado si faltan: eso sí es agnóstico y barato. Relájalo solo en salidas cortas de bajo riesgo (un titular, un meme) donde un reintento no duele.

Tabla de decisión por situación

Antes de instalar nada, sitúate. Esta es la tabla que usamos:

Situación ¿TOON en el prompt? ¿Qué hacer en la práctica
Array largo de objetos con las mismas claves (filas, catálogo, eventos homogéneos) encode a TOON solo en la construcción del prompt; respuesta en JSON
JSON pretty que mandas “porque se lee bien” Primero minifica; luego valora TOON Pretty nunca entra al modelo en producción
Datos profundamente anidados o con forma irregular por elemento No JSON compacto; recorta por estructura, no por bytes
API REST, almacenamiento, cola, contrato entre servicios Nunca JSON (o el formato nativo del sistema). Punto
Extracción estructurada donde quieres fijar columnas y N filas Sí, ayuda Cabecera {campos} + [N] como rieles; valida igual al volver
Pocas filas o payload ya pequeño (<~500 tokens de datos) Da igual El ahorro no paga el if en el código
Strings enormes de prosa dentro de campos No es problema de TOON Saca la prosa del JSON; delimitadores
Pipeline multi-etapa con techos de max_tokens Irrelevante el formato si la aritmética falla Cuadra presupuestos antes de comprimir

La decisión de colapsar a tabla en TOON no es capricho: requiere que todos los elementos sean objetos con el mismo set de claves y orden estable. Si eso no se cumple, el encoder no te va a regalar el formato CSV mágico, y tú no deberías forzar el disfraz.

Instalación y uso mínimo (para probarlo ya)

Librerías oficiales de la comunidad TOON:

  • TypeScript/JavaScript: npm install @toon-format/toon, encode() / decode().
  • Python: usa toon-format/toon-python. Ojo: el paquete python-toon (pip install python-toon) aparece en repos antiguos y está deprecado; no lo dejes en un requirements.txt nuevo sin mirar.
  • CLI: herramienta toon para archivos: encode toon input.json -o output.toon, decode toon data.toon -o output.json, con stdin/stdout si vas de tubería.

Flujo mínimo en cabeza de ingeniero, no de tutorial de gurú:

  1. Tienes un dict / objeto JSON válido en memoria (fuente de verdad).
  2. Si la tabla de arriba dice sí, toon_text = encode(data).
  3. Insertas toon_text en el prompt en un bloque claro (“DATOS:” + TOON).
  4. Instrucción de salida: JSON con esquema X (o structured output del proveedor).
  5. Parseas la respuesta como JSON. Si necesitas volver a TOON por algún motivo de depuración, decode, pero el camino feliz no lo toca.
  6. Mides tokens del prompt con y sin TOON en tu tokenizador / contador del proveedor. Sin medición en tu payload, no hay optimización: hay fe.

Opciones útiles en encode (según bindings): delimitador de campos (coma, tab, pipe) y marcador de longitud. Quédate con el default hasta que tengas un motivo; no conviertas el formato en un playground de flags.

Cómo se usa de verdad en un prompt (paso a paso)

Separa instrucciones, datos y formato de salida. Los datos son el candidato a TOON. Las instrucciones se quedan en prosa corta. El formato de salida se declara en JSON Schema o con un ejemplo mínimo, no con un sermón.

2. Encode solo el trozo gordo

No conviertas todo el prompt a TOON. TOON no es un idioma de system prompt. Es el envase del dataset. Si mezclas normas de negocio en la tabla, luego lloras cuando el decode de depuración no tiene sentido semántico.

3. Declara al modelo qué está leyendo

Una línea basta: “Los datos van en TOON (notación tabular: cabecera con campos y filas de valores). No devuelvas TOON; devuelve JSON con forma …” El modelo no necesita un curso; necesita la convención y el contrato de salida.

4. Fija el techo de salida con aritmética, no con buena voluntad

Comprimir la entrada no te salva si la etapa siguiente tiene un max_tokens imposible. Caso real de pipeline: una etapa recibía dos borradores generados con techo de 8192 tokens de salida y debía devolver el 100% de ese texto más campos JSON extra con techo 4096. A ~1,7–2 tokens por palabra en español, la truncación estaba garantizada por diseño. Cadena del fallo: finish_reason=length → JSON cortado → error de parseo → reintentos idénticos → parseo blando sin suelo de longitud → pieza degradada sin alerta. El arreglo fue configuración, no un formato nuevo.

Si además metes un modelo de razonamiento, el max_tokens cubre pensamiento + respuesta. El pensamiento se come una porción variable y crece con el contexto. Síntoma cabroncete: contenido vacío con finish_reason: stop, que parece respuesta corta legítima. Dimensiona el tope al peor caso (contexto lleno) con margen. Bajar el tope “para ahorrar” en razonadores es de iluso: el pensamiento se factura igual y te quedas sin salida útil.

5. Filtra en origen; no truncar por bytes

Otro modo de fallo que TOON no cura: raw[:6000] sobre un JSON de 20.000–50.000 caracteres. El sintetizador solo veía las primeras herramientas; el resto de métricas desaparecía sin error. Agravante clásico: poner delante un resumen lossy del modelo barato y detrás el JSON ya castrado, de modo que la “fuente primaria” es un eco degradado.

La pareja correcta es la del chunking por estructura en RAG: recorta por entidad, por herramienta, por ventana semántica. Y si el recopilador puede filtrar por id, nombre o región, diles en el prompt que usen el filtro. En un caso medido, pasar de “trae todo” a filtros explícitos bajó la entrada de ~20.000 a ~4.000 tokens (−80%) y subió la profundidad del análisis porque el modelo caro dejó de nadar en ruido.

Comprimir con TOON un dump sin filtrar es ponerle la faja al cerdo.

Errores comunes (los que comete todo el mundo la primera semana)

Tratar TOON como reemplazo de JSON en el sistema. Almacenamiento, APIs, eventos, fixtures de test: JSON. TOON solo en el borde del prompt. Si lo persistes “porque pesa menos”, has creado un dialecto sin ecosistema.

Comparar TOON contra JSON pretty y cantar victoria. Mide siempre contra JSON minificado. Si no, estás contando espacios como si fueran inteligencia artificial.

Forzar TOON en árboles anidados irregulares. El ahorro se diluye y la lectura humana del prompt empeora. Systenics y Tensorlake coinciden en el matiz: el dulce está en arrays uniformes.

Pedir la respuesta en TOON y parsear con regex de viernes. Contrato de salida en JSON. Structured output si el proveedor lo tiene y te compensa el acoplamiento. Delimitadores si hay prosa + metadatos.

Optimizar tokens de input y mirar solo el precio por millón. El coste real es el del trabajo terminado, no la fila de la tarifa. Un modelo “barato” que necesita tres reintentos, más contexto y más post-proceso te sale caro. TOON bien usado baja input en el caso tabular; no convierte un mal router de modelos en un buen sistema. Misma lógica que cuando orquestas agentes y se pisan el contexto: el formato es una palanca, no el diseño.

Instalar el paquete Python deprecado y clavar la versión en producción. Comunidad y repos apuntan a @toon-format/toon en JS y a toon-format/toon-python en Python. Verifica el paquete canónico antes del pip install de copiar-pegar.

No decidir qué pasa si el encode/decode o el delimitador fallan. Error tipado, log, reintento con JSON compacto de fallback. Silencio + parseo blando es cómo se cuelan piezas degradadas hasta el usuario.

Mini playbook de adopción en un servicio real

  1. Inventaría los prompts donde el bloque de datos supera ~1k tokens y es lista uniforme.
  2. Añade un flag prompt_data_format = json|toon con default json.
  3. Implementa encode solo en el builder del prompt; deja el dominio en JSON.
  4. Fija tests de round-trip (decode(encode(x)) == x) con tus fixtures reales.
  5. Mide tokens y calidad de tarea (no solo “¿parseó?”) en un canario.
  6. Activa TOON solo en los paths donde el ahorro sea material y la calidad no baje.
  7. Deja el fallback a JSON compacto automático si el encoder no puede tabularizar.

Si en el canario el ahorro es de 50 tokens, apaga el flag y sigue con tu día. La calidad del medio también se mide en no complicar el sistema por un café de tokens.

Cuándo no toques nada y te vayas a casa

  • El dataset no es tabular uniforme.
  • Ya mandas JSON minificado pequeño.
  • Tu cuello de botella es salida de razonamiento, herramientas ruidosas o presupuestos imposibles entre etapas.
  • Necesitas compatibilidad con un consumidor que solo traga JSON y no controlas el prompt builder.
  • Estás diseñando API pública o almacenamiento a largo plazo.

En esos casos, TOON es cosplay de optimización. Haz el trabajo aburrido: filtrar, partir por estructura, cuadrar max_tokens, medir coste por tarea terminada.

Cierre

TOON es una herramienta de borde, no una religión de datos. En nuestro payload, el ranking fue claro: pretty 4308, compacto 2892, TOON 2474. El salto gordo lo da dejar de ser romántico con el pretty-print; el salto fino lo da TOON cuando la tabla es de verdad una tabla. Arquitectura sin drama: JSON manda en el sistema, TOON comprime la ida al modelo, la vuelta es JSON. Si eso te parece poco glamuroso, bienvenido a la ingeniería que no se funde a fin de mes.

Abre un payload tuyo, cuéntalo en las tres formas, y deja que los números te digan si merece un encode o un cierre de pestaña.

Preguntas frecuentes

¿TOON sustituye a JSON en aplicaciones y APIs?

No. TOON es una capa de compresión para meter datos estructurados en prompts de LLM, no un formato de almacenamiento ni de API. JSON sigue siendo la fuente de verdad en disco, colas, tests y contratos entre servicios. Se codifica a TOON solo al construir el prompt y la respuesta del modelo se pide en JSON para parsear con las herramientas habituales.

¿Cuántos tokens se ahorran de verdad con TOON frente a JSON?

Depende del payload. Tensorlake midió 2.540 tokens en JSON minificado frente a ~1.020 en TOON (60%) en una tabla de 100 filas; Systenics habla de ~40% en sus pruebas; freeCodeCamp cita bandas 30-50% sin un único banco cerrado. En nuestro benchmark: JSON formateado 4308, JSON compacto 2892, TOON 2474. El ahorro serio aparece en arrays uniformes; en datos anidados irregulares se reduce.

¿Cómo se instala TOON en Python y en JavaScript?

En JavaScript/TypeScript: npm install @toon-format/toon y usas encode / decode. En Python el camino actual es el paquete de toon-format/toon-python; el python-toon antiguo está deprecado y no debería entrar en proyectos nuevos sin revisión. También existe la CLI toon para convertir archivos JSON ↔ TOON en terminal con redondeo determinista.

¿Cuándo no conviene usar TOON en un prompt?

Cuando los datos son profundamente anidados o irregulares, cuando el bloque ya es pequeño, o cuando el problema real es otro (truncado por bytes, presupuestos de salida imposibles, modelos de razonamiento que se comen el max_tokens pensando). Tampoco para APIs ni persistencia. En esos casos usa JSON compacto, filtra en origen y mide el coste por trabajo terminado, no solo tokens de input.

Fuentes

  1. TOON vs JSON: How Token-Oriented Object Notation Reduces LLM Token Costs | Systenics AI Blogsystenics.ai · 2026-01-24
  2. TOON vs JSON: A Token-Optimized Data Format for Reducing LLM Coststensorlake.ai · 2025-12-09
  3. JSON vs TOON (Token-Oriented Object Notation): Choosing the Right Data Format for LLMcommunity.ibm.com · 2025-11-20
  4. GitHub - xaviviro/python-toon: 🐍 TOON for Python (Token-Oriented Object Notation) Encoder/Decoder - Reduce LLM token costs by 30-60% with structured data.github.com
  5. What is TOON? How Token-Oriented Object Notation Could Change How AI Sees Datafreecodecamp.org · 2025-11-13