docs/guide/getting-started.md
Token-Oriented Object Notation is a compact, human-readable encoding of the JSON data model that minimizes tokens and makes structure easy for models to follow. It is intended for LLM input as a drop-in, lossless representation of your existing JSON.
TOON combines YAML's indentation-based structure for nested objects with a CSV-style tabular form for uniform arrays. Its sweet spot is uniform arrays of objects (multiple fields per row, same structure across items), reaching CSV-like compactness while adding explicit structure that helps LLMs parse and validate data reliably.
Think of it as a translation layer: use JSON programmatically, and encode it as TOON for LLM input.
Standard JSON is verbose and token-expensive. For uniform arrays of objects, JSON repeats every field name for every record:
{
"users": [
{ "id": 1, "name": "Ada", "role": "admin" },
{ "id": 2, "name": "Bob", "role": "user" }
]
}
YAML already reduces some redundancy with indentation instead of braces:
users:
- id: 1
name: Ada
role: admin
- id: 2
name: Bob
role: user
TOON goes further by declaring fields once and streaming data as rows:
users[2]{id,name,role}:
1,Ada,admin
2,Bob,user
The [2] declares the array length, letting LLMs answer dataset-size questions and detect truncation. The {id,name,role} declares the field names. Each row is a compact, comma-separated list of values. The pattern is the same throughout TOON: declare structure once, stream data compactly. The result lands close to CSV density with explicit structure preserved.
For a more realistic example, here's how TOON handles a dataset with both nested objects and tabular arrays:
::: code-group
{
"location": {
"city": "Berlin",
"country": "DE",
"units": "metric"
},
"alerts": [
"frost",
"wind"
],
"forecast": [
{
"day": "Mon",
"temp": {
"min": -2,
"max": 4
},
"condition": "snow",
"rainChance": 80
},
{
"day": "Tue",
"temp": {
"min": 1,
"max": 7
},
"condition": "cloudy",
"rainChance": 20
},
{
"day": "Wed",
"temp": {
"min": 3,
"max": 11
},
"condition": "sunny",
"rainChance": 5
}
]
}
location:
city: Berlin
country: DE
units: metric
alerts[2]: frost,wind
forecast[3]{day,temp{min,max},condition,rainChance}:
Mon,-2,4,snow,80
Tue,1,7,cloudy,20
Wed,3,11,sunny,5
:::
Notice how TOON combines YAML's indentation for the location object with inline form for the primitive alerts array and tabular form for the structured forecast array – where the uniform nested temp objects fold into the header as a nested field group (temp{min,max}). Each form is chosen automatically based on the data structure.
Maps of uniform objects collapse as well: the keyed tabular form turns them into tables whose rows carry their own keys.
TOON is optimized for specific use cases. It aims to:
TOON excels with uniform arrays of objects – data with the same structure across items. For LLM prompts, the format produces deterministic, minimally quoted text with built-in validation. Explicit array lengths ([N]) and field lists ({fields}) help detect truncation and malformed data, while tabular form declares the field list once rather than repeating it in every row.
::: tip The TOON format is stable, but also an idea in progress. Nothing's set in stone – help shape where it goes by contributing to the spec or sharing feedback. :::
TOON is not always the best choice. Consider alternatives when:
::: info For data-driven comparisons across different structures, see Benchmarks. When optimizing for latency, measure TTFT, tokens/sec, and total time for both TOON and JSON-compact, and use whichever is faster in your specific environment. :::
Install the library via your preferred package manager:
::: code-group
npm install @toon-format/toon
pnpm add @toon-format/toon
yarn add @toon-format/toon
:::
The CLI can be used without installation via npx, or installed globally:
::: code-group
npx @toon-format/cli input.json -o output.toon
npm install -g @toon-format/cli
pnpm add -g @toon-format/cli
yarn global add @toon-format/cli
:::
For full CLI documentation, see the CLI reference.
TOON files conventionally use the .toon extension. For HTTP transmission, the provisional media type is text/toon, always with UTF-8 encoding. While you may specify charset=utf-8 explicitly, it's optional – UTF-8 is the default assumption. This follows the registration process outlined in spec §17.
The examples below use the TypeScript library for demonstration, but the same operations work in any language with a TOON implementation.
Let's encode a simple dataset with the TypeScript library:
import { encode } from '@toon-format/toon'
const data = {
users: [
{ id: 1, name: 'Ada', role: 'admin' },
{ id: 2, name: 'Bob', role: 'user' }
]
}
console.log(encode(data))
Output:
users[2]{id,name,role}:
1,Ada,admin
2,Bob,user
Decoding is just as simple:
import { decode } from '@toon-format/toon'
const toon = `
users[2]{id,name,role}:
1,Ada,admin
2,Bob,user
`
const data = decode(toon)
console.log(JSON.stringify(data, null, 2))
Output:
{
"users": [
{ "id": 1, "name": "Ada", "role": "admin" },
{ "id": 2, "name": "Bob", "role": "user" }
]
}
Round-tripping is lossless: decode(encode(x)) always equals x (after normalization of non-JSON types like Date, NaN, etc.).
Now that you've seen your first TOON document, read the Format Overview for complete syntax details (objects, arrays, tabular forms, quoting rules), then explore Using TOON with LLMs to see how to use it effectively in prompts. For implementation details, check the API Reference (TypeScript) or the Specification (language-agnostic normative rules).