Most data formats were designed for one audience: humans or machines. JSON leans human. Binary formats like MessagePack lean machine. TOON is explicitly designed for a third audience that didn't exist when those formats were invented: large language models. Every syntax decision in TOON prioritises token efficiency — fitting maximum structured data into minimum tokens so you can pass more context to an AI without blowing your budget. This guide covers every TOON syntax feature, from simple scalars to the tabular notation that makes it genuinely different.
What Makes TOON Different
TOON stands for Token-Optimised Object Notation. The core idea is simple: data serialisation formats like JSON were designed long before per-token API pricing was a thing. JSON is fine for machine-to-machine communication, but when your payload is a 200-row dataset headed into a gpt-4o prompt, you're paying for every quote mark, every curly brace, and every repeated key name. TOON eliminates that waste. It installs as a single npm package — @toon-format/toon — and files use the .toon extension.
Scalar Values — Strings, Numbers, Booleans
TOON scalars look very similar to their JSON counterparts, with one important difference: string values do not require quotes unless they contain special characters like commas, colons, or brackets. This alone cuts a meaningful chunk of tokens out of text-heavy datasets.
// Numbers — exactly like JSON
42
3.14
-7
// Booleans — lowercase, same as JSON
true
false
// Strings — no quotes needed for simple values
hello
Alice
Widget ProWhen a string contains a comma, colon, or bracket, wrap it in double quotes just like JSON. So "New York, NY" needs quotes, but London does not. Simple rule, big savings.
Objects — Key:Value Pairs Without the Noise
TOON objects use curly braces with a key:value syntax. Keys are never quoted — that alone saves two characters per key compared to JSON. Pairs are comma-separated. No trailing commas, no colons after the final pair.
{name:Alice,age:31,city:London,active:true}Compare that to the equivalent JSON:
{"name": "Alice", "age": 31, "city": "London", "active": true}Same data, fewer characters, and the token savings compound dramatically when you're working with arrays of objects. Speaking of which...
Arrays — Ordered Lists of Values
Arrays in TOON use square brackets with comma-separated values — exactly like JSON, just without quotes on bare string values.
// Array of strings
[Alice,Bob,Carol]
// Array of numbers
[10,20,30,40,50]
// Mixed types (same rules as JSON)
[Widget Pro,29.99,true,101]
// Array of objects
[{id:1,name:Alice},{id:2,name:Bob}]Arrays of objects work, but this is where TOON's killer feature comes in. If you have more than two or three rows of structured data, the tabular notation is dramatically more efficient.
Tabular Notation — The Feature That Changes Everything
Tabular notation is TOON's headline feature. It's designed for the scenario you hit constantly in real work: a list of similar objects — products, users, transactions, log entries — where repeating the keys on every row is pure waste. The syntax is:
name[count]{col1,col2,col3,...}:
row1val1,row1val2,row1val3
row2val1,row2val2,row2val3Breaking it down: name is the dataset's label, [count] is the number of data rows (required — it tells the parser exactly how many lines to read), {col1,col2,...} is the header row, the colon : ends the header, and each subsequent indented line is one row of values. Here's a real products example:
products[5]{id,name,price,inStock,category}:
101,Widget Pro,29.99,true,Tools
102,Gadget Plus,49.99,true,Electronics
103,Thing Basic,9.99,false,Misc
104,Super Doohickey,74.99,true,Electronics
105,Budget Widget,14.99,true,ToolsNow picture that same data as an array of JSON objects. You'd write "id", "name", "price", "inStock", and "category" five times each — plus all the surrounding braces, brackets, and quotes. The tabular TOON representation is roughly 60% smaller in token count for this shape of data.
A user dataset follows the same pattern:
users[4]{id,username,email,role,active}:
1,alice_dev,[email protected],admin,true
2,bob_writer,[email protected],editor,true
3,carol_ops,[email protected],viewer,false
4,dan_qa,[email protected],editor,true[count] is part of the syntax and must match the actual number of data rows. The parser uses it to know when the table ends — especially useful when TOON is embedded inside a larger structure. Use the TOON Validator to catch count mismatches instantly.Nesting — Objects, Arrays, and Tabular Together
TOON supports nesting in the places you'd expect. An object can contain an array value. A tabular row can contain an object. This lets you represent real-world data that doesn't fit perfectly into flat rows.
Object containing an array:
{name:Alice,roles:[admin,editor],active:true}Tabular data with an embedded object in one column (useful for address data, metadata, etc.):
orders[3]{orderId,customer,total,address}:
1001,alice_dev,89.97,{city:London,country:UK}
1002,bob_writer,49.99,{city:Berlin,country:DE}
1003,carol_ops,124.50,{city:Paris,country:FR}Keep nesting shallow when possible. Two or three levels deep is where TOON still wins on token count. Deeply recursive structures are better served by JSON, which has richer tooling for schema validation — see the MDN JSON reference if you need that.
Working with the npm Package
Install with npm or any compatible package manager. TOON works in Node.js and modern browsers.
npm install @toon-format/toonThe package exports two functions: encode and decode. That's the entire public API — intentionally minimal.
import { encode, decode } from '@toon-format/toon';
// decode: TOON string → JS value
const toonString = `products[3]{id,name,price,inStock}:
101,Widget Pro,29.99,true
102,Gadget Plus,49.99,true
103,Thing Basic,9.99,false`;
const data = decode(toonString);
console.log(data);
// [
// { id: 101, name: "Widget Pro", price: 29.99, inStock: true },
// { id: 102, name: "Gadget Plus", price: 49.99, inStock: true },
// { id: 103, name: "Thing Basic", price: 9.99, inStock: false }
// ]
// encode: JS value → TOON string
const users = [
{ id: 1, username: 'alice_dev', active: true },
{ id: 2, username: 'bob_writer', active: false }
];
const toon = encode(users, { indent: 2 });
console.log(toon);
// users[2]{id,username,active}:
// 1,alice_dev,true
// 2,bob_writer,falseThe { indent: 2 } option controls indentation of row values. You can also use encode on plain objects and primitive values, not just arrays — it picks the most compact TOON representation automatically. Paste the output into the TOON Formatter to inspect and pretty-print it.
Common Mistakes
These are the errors that bite developers new to TOON, usually within the first hour:
- Wrong row count in tabular notation. Writing
products[3]but then including 4 data rows will cause a parse error or silently drop the last row depending on the parser version. Count your rows and keep the number up to date. The TOON Validator catches this immediately. - Quoting object keys.
{"name":Alice}is invalid TOON — keys are never quoted. Drop the quotes:{name:Alice}. - Forgetting the colon after the header.
products[2]{id,name}followed by a newline will fail. You need the trailing colon:products[2]{id,name}:. - Using spaces around the colon in key:value pairs.
{name : Alice}is not valid. No spaces:{name:Alice}. - Embedding commas in unquoted string values. If a product name is "Bolts, Nuts & More", you must quote it in tabular rows:
101,"Bolts, Nuts & More",4.99,true. - Expecting JSON output from decode on scalars.
decode("42")returns the JavaScript number42, not a JSON object. TOON decodes to native JS types.
Converting Between TOON and JSON
TOON and JSON are fully interconvertible — TOON is a superset of the same logical data model that JSON serialises. Use JSON to TOON to shrink an existing dataset before sending it to an LLM, and TOON to JSON to convert back when you need to feed the result into a JSON-only downstream system. The encode and decode functions handle this programmatically if you're automating the workflow in Node.js. The underlying data structure spec is closely related to concepts from the JSON global in JavaScript.
Wrapping Up
TOON syntax is intentionally compact. No quoted keys, no repeated key names in tables, no obligatory quotes on simple string values. Once you've written a tabular block by hand you'll immediately see why — a dataset that takes 40 lines of JSON fits in 8 lines of TOON. The npm package at npmjs.com/@toon-format/toon keeps the API surface tiny: encode and decode, nothing else to learn. Use the TOON Formatter to pretty-print, TOON Validator to catch syntax errors, JSON to TOON to convert your existing data, and TOON to JSON when you need the result back in standard form.