TOON Nested Field Groups: Nested Objects in TOON Tables
TOON nested field groups put uniform nested objects inside table rows with headers like customer{name,country}. Contacts data shrank 66.5% vs JSON.
Nested field groups are a TOON v4 feature that lets an array of objects stay in compact table form even when each object contains nested objects. A header such as customer{name,country} declares the sub-keys once, and every row lists the nested values inline. On the official contacts dataset, this cut tokens by 66.5% compared with pretty-printed JSON.
What are nested field groups in TOON?
Before spec 4.0, TOON tables could only hold primitive columns. If one field in an array of objects was itself an object, the encoder gave up on the table and fell back to the indented list form, repeating every key on every item. Spec 4.0 added nested field groups (RFC #46), so a column whose values are all objects with the same keys can now stay inside the table. The TOON spec changelog lists it among the 4.0 additions next to keyed tabular form and full-line comments.
The idea is simple. The header names the nested object and lists its sub-keys in braces. Each row then flattens the nested values into ordinary cells. Here is real output from @toon-format/toon 4.1.1:
orders[2]{id,customer{name,country},total}:
1,Ada,UK,49.99
2,Bob,US,199The header says there are two orders and that each has an id, a customer object with name and country, and a total. Each row holds four cells, one per leaf field. Decoding the snippet gives back the original nested structure, with customer as a real object, not a flattened string.
If you are new to v4, start with our overview of what changed in TOON v4. This post focuses on one feature.
How much do nested field groups save?
The official token-efficiency benchmark includes a dataset built for this feature: contacts with nested address and plan groups. All counts use the o200k_base tokenizer.
| Format | Tokens | TOON saving |
|---|---|---|
| TOON (nested groups) | 26,726 | baseline |
| JSON compact | 46,791 | 42.9% |
| YAML | 55,475 | 51.8% |
| JSON (pretty) | 79,779 | 66.5% |
| XML | 90,306 | 70.4% |
That is the largest reduction against JSON in the published token-efficiency results. It even beats the flat employee table (60.7% fewer tokens than JSON) because nested JSON pays for its keys twice. It repeats the outer key and every inner key, plus the extra braces and indentation, once per record. Nested field groups remove all of that.
For context, TOON averages about 43% fewer tokens than JSON on the official TOON benchmark, from about 33% on the mixed/nested track to about 59% on flat tables. The current run, on spec v4.1, reports 42.6% fewer tokens with 72.2% accuracy for TOON against 71.4% for JSON over 5,856 LLM calls (retrieval-accuracy results). Contacts sits well above that average because it is 100% tabular once nested groups are allowed.
What does a nested table look like next to JSON?
Here are three contact records in pretty-printed JSON, the way many APIs return them:
{
"contacts": [
{
"id": 1,
"name": "Ada Lovelace",
"address": {
"city": "London",
"country": "UK"
},
"plan": {
"tier": "pro",
"seats": 5
}
},
{
"id": 2,
"name": "Grace Hopper",
"address": {
"city": "Arlington",
"country": "US"
},
"plan": {
"tier": "team",
"seats": 12
}
},
{
"id": 3,
"name": "Alan Turing",
"address": {
"city": "Manchester",
"country": "UK"
},
"plan": {
"tier": "free",
"seats": 1
}
}
]
}The same data encoded by TOON 4.1.1:
contacts[3]{id,name,address{city,country},plan{tier,seats}}:
1,Ada Lovelace,London,UK,pro,5
2,Grace Hopper,Arlington,US,team,12
3,Alan Turing,Manchester,UK,free,1Each row has six cells because the header has six leaf fields: id, name, city, country, tier and seats. The spec calls this order a "depth-first, pre-order walk of the field list (nested groups expanded in place)". Each nested group's cells sit in the same position as the group in the header.
Groups can also nest inside groups. Here a geo group contains a loc group:
events[2]{id,geo{loc{lat,lon},tz}}:
1,51.5,-0.12,Europe/London
2,40.7,-74,America/New_YorkWhen does TOON use a nested field group?
The rules are in section 9.3 of the TOON specification. A column is nested-uniform when "every value is a non-empty object, all these objects have the same set of keys (order per object MAY vary), and every sub-column is itself uniform-primitive or nested-uniform." The array as a whole still has to pass the usual table checks. Every element must be an object, all elements must have the same keys, and every column must be either primitive or nested-uniform.
Spec 4.1 also makes tabular form mandatory whenever detection succeeds. You do not need to set an option: any conforming 4.1 encoder produces the nested header automatically when the data qualifies.
What disqualifies an array from table form?
Section 9.3 is strict. One bad column "disqualifies the whole array", and the encoder falls back to list form. These are the cases you will hit most often:
- A null mixed with objects. If one customer is
null, the column mixes a primitive with objects. - An array anywhere inside the group. A
tagslist insidecustomerblocks the table. - Different sub-keys. If one customer has
countryand another does not, the objects do not share the same set of keys. - Empty objects. Any
{}in the array forces list form.
Here is the null case in real encoder output. One null customer turns the whole array into list form:
orders[2]:
- id: 1
customer:
name: Ada
country: UK
- id: 2
customer: nullThe fix usually happens before encoding. You can fill missing sub-fields with an explicit empty string or sentinel value. You can drop optional nested arrays the model does not need. Or you can split rare outliers into a separate block. Only do this when the change does not alter meaning: a missing customer and a customer with blank fields are not the same thing.
Do nested field groups work with keyed tables and delimiters?
Yes. Nested groups combine with the other v4 table features. With the pipe delimiter, the header and rows switch separators together:
orders[2|]{id|customer{name|country}|total}:
1|Ada|UK|49.99
2|Bob|US|199They also work inside keyed tabular form, which encodes an object whose values are uniform records. Our guide to keyed tables covers that syntax in detail. Combined, they look like this:
users[2:]{name,address{city,country}}:
u1: Ada,London,UK
u2: Bob,Austin,USFor choosing between comma, tab and pipe, see TOON delimiters explained.
What are the trade-offs?
Nested groups make rows harder to read. In 1,Ada Lovelace,London,UK,pro,5 the model has to map the fifth cell back to plan.tier by counting through the header. The benchmark does not report accuracy for the contacts dataset on its own. If your queries depend on deep fields, run an accuracy check on your own data. Do not assume the token savings come with no cost in comprehension.
Wide headers are another risk. A group with a dozen sub-keys produces long rows of bare values. The TOON README still says that deeply nested or non-uniform data is often better served by compact JSON. Nested groups widen what TOON can handle as a table, but they do not change that advice for irregular data.
Also note that older guides, including our own nested data handling post, describe the v3 behavior, where any nested object forced list form. That is no longer true for uniform nested objects.
How do I try it on my data?
Paste your JSON into the JSON to TOON converter and check whether the header contains braces inside braces. If it does not, find the column that broke uniformity. It is usually a null, an optional sub-key or an embedded array. For programmatic use, encode() from @toon-format/toon 4.x applies the rules automatically. The TOON docs cover the API.
Frequently Asked Questions
What is a nested field group in TOON?
It is a TOON v4 table header entry such as customer followed by its sub-keys in braces. It lets a column whose values are all objects with the same keys stay inside a compact table. Each row lists the nested values inline, in depth-first order, so nested keys are written once instead of once per record.
Which TOON version supports nested field groups?
Nested field groups were added in TOON spec 4.0 and are in spec 4.1, implemented by the @toon-format/toon library version 4.x. Version 3 encoders cannot produce them, and older decoders cannot read them, so upgrade decoders before encoders when you migrate.
Why did my nested array fall back to list form?
One column broke the uniformity rule in spec section 9.3. The usual causes are a null mixed with objects, an array inside the nested object, objects with different sub-keys, or an empty object. Any one of these disqualifies the whole array, so the encoder uses indented list form instead.
How many tokens do nested field groups save?
On the official contacts benchmark with nested address and plan groups, TOON used 26,726 tokens against 79,779 for pretty JSON, a 66.5 percent reduction, and 42.9 percent fewer than compact JSON. Results on your data depend on how uniform the nested objects are.
Recommended Reading
TOON Keyed Tables: Encoding Maps of Objects in Fewer Tokens
TOON keyed tables collapse objects keyed by ID or name, like feature flags or user maps, into one table. Syntax, rules and the 54.6% savings vs JSON.
TOON vs Minified JSON: When Compact JSON Wins
The latest TOON benchmark shows compact JSON beats TOON on mixed, nested data, while TOON wins big on uniform tables. Here is how to choose for your payload.
TOON v4: Keyed Tables, Nested Field Groups and Comments
TOON spec 4.1 adds keyed tables for maps of objects, nested field groups and full-line comments, and drops key folding. What changed and why it matters.