9 min read

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.

By json2toon.co

TOON v4 is the current version of Token-Oriented Object Notation. Spec 4.0 (July 22, 2026) added three things: keyed tables for maps of uniform objects, nested field groups inside tabular headers, and full-line # comments. It also removed key folding. Spec 4.1 followed four days later, and @toon-format/toon 4.1.1 implements it.

What changed in TOON v4 at a glance?

Version 4 is a major release, and most of it widens the set of data that gets the compact table treatment. The spec changelog lists the changes; this table sums up the ones you will notice.

AreaSpec 3.xSpec 4.x
Maps of uniform objects (flags, records by ID)Nested key-value blocksKeyed table: flags[3:]{enabled,rollout}:
Arrays whose rows contain uniform sub-objectsList form, one indented block per itemNested field group: {id,customer{name,country},total}
CommentsNoneFull-line # comments, stripped by decoders
Key folding (a.b.c: 1)Optional encoder featureRemoved, along with path expansion
Unquoted numbers like .5, 0x10, 1_000Left to host parsersStrict grammar: these decode as strings
Indentation depth jumpsTolerated by some decodersStrict-mode error

Why did the library jump from 2.x to 4.0?

Until July 2026 the spec and the TypeScript reference library had separate version numbers. Spec 3.0 shipped on November 24, 2025, together with library 2.0.0. The library then went through 2.1.0, 2.2.0, 2.3.0 and 2.3.1. On July 22, 2026 it went straight to 4.0.0, so the major version now matches the spec. There is no 3.x on npm. Version 4.1.0 followed on July 26 and 4.1.1 on August 5, according to the GitHub releases page.

The release lands on a much bigger install base than earlier versions. Monthly npm downloads of @toon-format/toon grew from about 984K in January 2026 to about 5.44M in September 2026, according to the npm downloads API. Spec 4.1 is still marked "Working Draft" in SPEC.md. It also asks implementations to say which version they target (for example toon-spec: 4.1), which helps when you mix ports in other languages.

What are keyed tables in TOON v4?

A keyed table encodes an object whose values all share one shape, such as feature flags keyed by name or users keyed by ID. Before v4, only arrays could become tables, so these maps were written out as nested blocks with every field name repeated. Here is the same data in JSON and in TOON 4.1.1 encoder output:

{
  "flags": {
    "darkMode": { "enabled": true, "rollout": 50 },
    "newCheckout": { "enabled": false, "rollout": 0 },
    "betaSearch": { "enabled": true, "rollout": 10 }
  }
}
flags[3:]{enabled,rollout}:
  darkMode: true,50
  newCheckout: false,0
  betaSearch: true,10

The colon after the count ([3:]) marks the keyed form, and each row starts with its own key. The official benchmark added a "feature flags keyed by name" dataset for this. On it, TOON uses 54.6% fewer tokens than JSON and 32.8% fewer than minified JSON (token-efficiency results). Detection needs at least two entries, and every value must be a non-empty object with the same keys. Single-entry maps stay nested.

What are nested field groups?

Nested field groups fix the most common reason an array lost its table in v3: a column that holds a small object instead of a primitive. An order with a customer sub-object used to push the whole array into list form. This is the output of library 2.3.1 (spec 3.x):

orders[2]:
  - id: 1
    customer:
      name: Ada
      country: UK
    total: 49.99
  - id: 2
    customer:
      name: Bob
      country: US
    total: 199

And the same input encoded by 4.1.1:

orders[2]{id,customer{name,country},total}:
  1,Ada,UK,49.99
  2,Bob,US,199

Rows stay flat. The header describes how cells map back to the nested object through a depth-first walk, with no depth limit. Per the changelog, output is byte-identical to v3 wherever no group applies, so flat tables do not change. The benchmark's "contacts with nested address and plan groups" dataset shows the effect: TOON is 66.5% smaller than JSON and 42.9% smaller than minified JSON (source). Groups apply only when every sub-object has the same keys. A column that mixes null with objects still falls back to list form.

How do comments work in TOON v4?

A line whose first non-space character is # is a comment. Decoders strip it before anything else runs. The spec is explicit in §5.1: "Comments are full-line only: a '#' anywhere else on a line is ordinary content, and no inline or trailing comment form exists." Comments are for people who write TOON by hand, such as prompt templates or fixtures. Encoders must not emit them, so encode() never adds one.

This hand-written input decodes cleanly with 4.1.1:

# Exported 2026-10-01 from the billing service
config:
  # request timeout in milliseconds
  timeout: 5000
  retries: 3

decode() result: {"config":{"timeout":5000,"retries":3}}

A trailing comment does not work. timeout: 5000 # milliseconds decodes to the string "5000 # milliseconds", so a number quietly becomes a string. To keep data away from the comment rule, v4 encoders quote any string value that starts with #:

tags: []
note: "#not a comment"
channel: "#general"
items[1]{id,name}:
  1,A

Why was key folding removed?

Key folding was an optional v3 encoder feature. It collapsed single-key chains like {"db":{"pool":{"max":20}}} into db.pool.max: 20, and a matching decoder option (expandPaths) turned them back into objects. Spec 4.0 removes both completely: the keyFolding and flattenDepth encoder options and the expandPaths decoder option. Dotted keys are now always literal keys, which is what v3 did by default anyway.

That means a document encoded without folding is unaffected. A document encoded with folding now decodes to an object with a literal "db.pool.max" key. In 4.1.1, passing keyFolding: "safe" does not throw. The option is ignored and the output stays nested, so check for it in your code.

What else changed in spec 4.0 and 4.1?

  • A strict number grammar. Unquoted .5, 1., +5, Infinity, NaN, 0x10 and 1_000 decode as strings. Decoders may not hand tokens to looser host parsers.
  • Safe prototype keys. __proto__, constructor and prototype are ordinary keys, and decoding must not change the host object model.
  • Indentation depth jumps (skipping a level) are a strict-mode error.
  • Encoders lost their freedom in 4.1. Tabular form is mandatory wherever detection succeeds, and empty arrays are always key: [], never key[0]:. A leading byte-order mark is stripped.
  • The indentSize option name (renamed from indent in spec 3.3) is now used throughout. Library 4.1.0 accepts it.

Delimiters did not change. Comma is the default, and tab and pipe are declared in the header (rows[2|]{a|b}:). Our delimiter guide covers when to switch. For the full grammar, see the TOON specification overview.

Did the benchmark numbers change with v4?

Yes. Library 4.1.0 added keyed and nested-group datasets to the benchmark, and the suite was re-run on newer models. The current run covers 5,856 LLM calls (244 questions, 6 formats, 4 models: Claude Haiku 4.5, Gemini 3.6 Flash, GPT-5.4 nano and Grok 4.5). TOON scored 72.2% accuracy vs 71.4% for JSON while using 42.6% fewer tokens (retrieval-accuracy results).

Keep two caveats in mind. First, the accuracy figures come with Wilson 95% intervals (TOON ±2.8). When intervals overlap, the benchmark itself says the difference "is not statistically meaningful." The token savings are the solid result; the accuracy gap is not. Second, the savings depend on data shape: 58.7% on the flat-only track but 32.7% on mixed structures. On mixed data, TOON is actually 1.6% larger than minified JSON. In general prose, "about 40% fewer tokens" is the fair summary. Our guide to when not to use TOON explains the trade-offs.

Should you upgrade to TOON v4 now?

For most teams, yes. The new forms only apply where they save tokens. If TOON only flows one way, from your code into a prompt, upgrading the encoder is low risk. If other services or stored files decode TOON, upgrade the decoders first. The changelog warns that strict v3 decoders reject keyed headers, and non-strict ones "mis-decode it silently." Also scan stored v3 documents for lines that begin with #, because v4 now reads them as comments.

To see what v4 output looks like for your own payloads, paste them into the free JSON to TOON converter and compare token counts before you change production code.

Frequently Asked Questions

What is new in TOON v4?

TOON spec 4.0 (July 22, 2026) added keyed tables for maps of uniform objects, nested field groups for arrays whose rows contain uniform sub-objects, and full-line # comments. It removed key folding and path expansion. Spec 4.1 (July 26, 2026) made tabular output mandatory wherever it applies and fixed the empty-array form.

Why is there no TOON 3.x library?

The specification and the npm package used to have separate version numbers: spec 3.0 shipped with library 2.0.0. The package went from 2.3.1 straight to 4.0.0 on July 22, 2026, so its major version now matches the spec. No 3.x release of @toon-format/toon was ever published.

Can I put inline comments in TOON?

No. TOON v4 comments are full-line only: a line whose first non-space character is # is removed by the decoder. A # anywhere else is ordinary content, so timeout: 5000 # milliseconds decodes to the string "5000 # milliseconds", not the number 5000. Encoders never emit comments.

Does TOON v4 output differ from v3 for my existing data?

Only where the new forms apply. Nested field groups produce byte-identical output to v3 wherever no group applies. Output changes for maps of uniform objects (now keyed tables), arrays with uniform nested objects (now nested field groups), strings starting with # (now quoted) and data that relied on key folding.

Recommended Reading

TOONTOON v4SpecificationRelease NotesToken EfficiencyLLM