Description
@tehw0lf/n8n-nodes-toon


This is an n8n community node that provides bidirectional conversion between TOON (Token-Oriented Object Notation) and JSON formats. TOON is a line-oriented, indentation-based format optimized for LLM prompts and structured data interchange.
n8n is a fair-code licensed workflow automation platform.
Table of Contents
- What is TOON?
- Installation
- Operations
- Configuration Options
- Usage Examples
- Use Cases
- Compatibility
- Zero Dependencies
- Resources
- Line-oriented and indentation-based — similar to YAML but more deterministic
- Minimal quoting — strings are quoted only when necessary
- Explicit array lengths — detect truncation and malformed data
- Tabular arrays — declare field lists once, then list values row by row
- Multiple delimiters — comma, tab, or pipe for different use cases
- Zero external dependencies — pure Node.js implementation
What is TOON?
TOON (Token-Oriented Object Notation) is a compact text format that encodes the JSON data model with explicit structure and minimal quoting. It’s particularly efficient for arrays of uniform objects — common in data exports, API responses, and LLM prompts.
Key Features
Quick Example
JSON:
{
"users": [
{"id": 1, "name": "Alice", "role": "admin"},
{"id": 2, "name": "Bob", "role": "user"}
]
}
TOON:
users[2]{id,name,role}:
1,Alice,admin
2,Bob,user
The TOON format is 50% more compact than JSON for tabular data, making it ideal for:
Installation
Follow the n8n community nodes installation guide.
npm
npm install @tehw0lf/n8n-nodes-toon
n8n Cloud
In n8n Cloud or self-hosted n8n (v0.200+):
1. Go to Settings → Community Nodes
2. Select Install
3. Enter @tehw0lf/n8n-nodes-toon and agree to the risks
4. Click Install
The TOON node will appear in your node palette under the Transform category.
Operations
The TOON node supports two operations:
1. JSON to TOON
Convert JSON data to TOON format.
Input: JSON object or array
Output: TOON formatted text
Use case: Prepare data for LLM prompts, compact serialization
2. TOON to JSON
Parse TOON formatted text back to JSON.
Input: TOON formatted text
Output: JSON object or array
Use case: Parse LLM responses, deserialize TOON data
Configuration Options
Encoding Options (JSON→TOON)
| Option | Type | Default | Description |
|——–|——|———|————-|
| Indent Size | Number | 2 | Spaces per indentation level |
| Delimiter | Choice | comma | Delimiter for array values (comma, tab, pipe) |
| Key Folding | Choice | off | Collapse single-key chains (off, safe) |
| Flatten Depth | Number | 999 | Maximum segments to fold (999 = unlimited) |
| Include Token Metrics | Boolean | false | Add token count comparison to output |
Decoding Options (TOON→JSON)
| Option | Type | Default | Description |
|——–|——|———|————-|
| Expected Indent Size | Number | 2 | Expected indentation for validation |
| Strict Mode | Boolean | true | Enforce array counts and indentation |
| Expand Paths | Choice | off | Split dotted keys (off, safe) |
Input/Output Configuration
| Option | Type | Default | Description |
|——–|——|———|————-|
| Input Data | String | ={{ $json }} | Data to convert. Supports drag-and-drop, field names, dot notation, and expressions. Auto-detects input type. |
| Output Field | String | data | Field name for output |
#### Input Data Details
The Input Data field auto-detects the input type:
data)users[0].name)={{ $json.users.filter(u => u.active) }})Token Metrics Output
When Include Token Metrics is enabled for JSON→TOON conversion, the output includes a tokenMetrics object:
{
"data": "users[2]{id,name}:n 1,Alicen 2,Bob",
"tokenMetrics": {
"json": 123,
"toon": 58,
"saved": 65,
"reduction": 0.5285
}
}
Failed Items (Continue On Fail)
When On Error is set to a Continue option and an item fails, the failed item carries all fields of its input item plus the error message. Input fields named error are overwritten.
error (the error message) and details.itemIndex. Input fields named details are overwritten.error (the error message) and itemIndex. Input fields named itemIndex are overwritten.Usage Examples
Example 1: LLM Context Preparation
Workflow: Fetch Users → JSON to TOON → Send to LLM
Use TOON to fit more context into LLM token limits while maintaining readability.
Input (JSON):
{
"users": [
{"id": 1, "name": "Alice", "role": "admin", "active": true},
{"id": 2, "name": "Bob", "role": "user", "active": true},
{"id": 3, "name": "Charlie", "role": "user", "active": false}
]
}
Output (TOON – comma delimiter):
users[3]{id,name,role,active}:
1,Alice,admin,true
2,Bob,user,true
3,Charlie,user,false
Token Savings: ~40-50% fewer tokens than equivalent JSON for structured data.
Example 2: Parse LLM Structured Output
Workflow: Send Prompt to LLM → TOON to JSON → Process Data
LLMs can generate TOON format more reliably than JSON due to simpler syntax.
LLM Output (TOON):
result:
tasks[3]{name,priority,status}:
"Update docs",high,pending
"Fix bug #123",high,done
"Refactor code",low,pending
summary: "3 tasks identified"
Parsed JSON:
{
"result": {
"tasks": [
{"name": "Update docs", "priority": "high", "status": "pending"},
{"name": "Fix bug #123", "priority": "high", "status": "done"},
{"name": "Refactor code", "priority": "low", "status": "pending"}
],
"summary": "3 tasks identified"
}
}
Example 3: Working with CSV Data
n8n has excellent built-in CSV support via the “Extract from File” node. Use TOON for transformations:
Workflow: Read File → Extract from CSV → JSON to TOON → Transform → TOON to JSON → Use Data
1. Use n8n’s “Extract from File” (CSV) node to parse CSV files
2. The extracted data is already JSON (one item per row)
3. Use “JSON to TOON” to convert to TOON format for LLM processing
4. Use “TOON to JSON” to convert back to JSON for further processing
Example 4: Key Folding for Nested Data
Workflow: API Request → JSON to TOON (Key Folding: Safe) → Transform
Simplify deeply nested JSON structures.
Input:
{
"user": {
"profile": {
"name": "Alice",
"email": "[email protected]"
}
}
}
Output (with Key Folding):
user.profile.name: Alice
user.profile.email: [email protected]
Example 5: Different Delimiters
Use tab delimiters for data with commas in values.
TOON (tab delimiter):
products[2]{id name price}:
1 "Widget, Small" 9.99
2 "Gadget, Large" 19.99
Use Cases
1. LLM Integration
Problem: JSON wastes tokens on quotes, brackets, and redundant keys.
Solution: TOON reduces token usage by 40-50% for structured data.
Workflow: Data Source → JSON to TOON → LLM → TOON to JSON → Process
2. API Response Transformation
Problem: API responses are verbose JSON that’s hard to read in logs.
Solution: Convert to TOON for compact, human-readable logging.
Workflow: API Request → JSON to TOON → Log/Store → TOON to JSON → Use
3. Data Format Conversion
Problem: Need to transform data between different formats for different systems.
Solution: Use TOON as an intermediate format for transformations.
Workflow: Extract from CSV → JSON to TOON → Transform → TOON to JSON → Send to API
4. Configuration Management
Problem: JSON config files are verbose and don’t support comments well.
Solution: Store configs in TOON format for better readability.
Workflow: Read TOON Config → TOON to JSON → Apply Settings
5. Report Generation
Problem: Need to generate readable reports from structured data.
Solution: Convert to TOON for human-friendly text representation.
Workflow: Fetch Data → JSON to TOON → Format Report → Send Email
Compatibility
Specification Compliance
This node implements TOON Specification v4.4 in full for the decoder and, using the default options, for the encoder; every normative requirement of Sections 1–16 is implemented. Two additional convenience options fall outside the specification and are documented as non-spec extensions below.
Implemented Features
✅ Core Features (100%)
[N][N]{field1,field2}:orders[2]{id,customer{name,country},total}:users[2:]{age,city}:Non-Spec Extensions
⚠️ These two options are this node’s own convenience features, not part of the TOON specification. v4.4 treats dotted keys as ordinary literal keys with no structural meaning (§8), so output produced with key folding enabled decodes to dotted keys — not nested objects — in any conforming TOON implementation. Both default to off; leave them off for interoperable output.
keyFolding: "safe") – Collapse nested single-key objects into dotted paths (e.g., {a: {b: {c: 1}}} → a.b.c: 1). While it is on, a literal key that contains a dot and whose dot-separated segments are all identifiers (such as c.d) is written quoted ("c.d": 1), so that Path Expansion does not split it. This deviates from §7.3, which leaves such keys unquoted, and applies only while the option is on and only outside arrays.expandPaths: "safe") – Expand dotted keys back into nested objects during decodingNotes on Encoder Output
The encoder selects a form from each value’s shape and position, as §1.4 requires, rather than by preference:
key: [] in field position and [] at the root; the legacy key[0]: form is accepted on decode but never emitted.Documented Implementation Behavior
The specification requires implementations to document the following (§2, §3, §4, §13.2):
Host-type normalization (§3). Values are normalized to the JSON data model before encoding:
| Host value | Encoded as |
|—|—|
| NaN, Infinity, -Infinity | null |
| undefined, functions, symbols | null |
| Objects with a toJSON() method | the normalized result of toJSON(), applied recursively |
| Date | ISO 8601 string via the built-in toJSON() (quoted, since it contains colons) |
Numeric domain and out-of-range policy (§4). Numbers are IEEE-754 doubles, the JavaScript numeric domain. Decoded numeric tokens outside that domain return the nearest approximate double rather than erroring or returning a string; values beyond Number.MAXSAFEINTEGER may therefore lose precision on round-trip. Tokens are classified by the §4 number grammar, not by Number(), so .5, 1., +5, 0x10, Infinity, and NaN all decode as strings.
Object key order (§2). Key order is preserved as encountered, except that tabular and keyed tabular forms reorder to the header’s field order. One deviation is inherent to the JavaScript object model: integer-like keys are hoisted and ordered numerically ahead of string keys, so a document with keys b, 1, a decodes to an object ordered 1, b, a. Array order is always preserved.
Prototype keys (§15). Decoded keys are installed with Object.defineProperty, so proto, constructor, and prototype become ordinary own data properties and decoding never mutates a prototype chain. The encoder likewise emits own proto, constructor, and prototype keys as ordinary keys, and key folding never starts or continues a dotted chain through such a key.
Round-Trip Guarantee
All JSON data can be encoded to TOON and decoded back to JSON with full fidelity. The implementation passes all conformance requirements for encoders and decoders per the specification.
Advanced Features
Strict Mode
When enabled (default), the decoder validates:
Disabling strict mode does not make the decoder lenient in general: every error condition of the specification still applies. Non-strict mode only applies the specification’s five recoveries (§14.4):
Malformed headers, row width mismatches, over-indented lines, a first line indented at the root and trailing content after a root form are errors in both modes.
The non-spec expandPaths option adds one further non-strict recovery: when two keys meet at the same key during path expansion (a literal key and an expanded path, or two expanded paths) and are not two objects (which merge), strict mode reports an error and non-strict mode resolves the conflict by last-write-wins, keeping the position of the key’s first occurrence. See Path Expansion.
Path Expansion
Convert dotted keys into nested objects:
TOON:
user.name: Alice
user.email: [email protected]
JSON (with expandPaths: safe):
{
"user": {
"name": "Alice",
"email": "[email protected]"
}
}
When two keys meet at the same key during path expansion (a literal key and an expanded path, or two expanded paths), two objects are merged, whichever line comes first. Any other overlap is an error in strict mode, whichever line comes first, and in non-strict mode the later line wins (the key keeps the position of its first occurrence).
Dotted keys are expanded at any depth, including inside the object value of an expanded dotted key: a.b: with a nested c.d: 1 decodes to { "a": { "b": { "c": { "d": 1 } } } }. Arrays are not searched for dotted keys. Quoted keys are never expanded: "c.d": 1 decodes to { "c.d": 1 }, and in non-strict mode the last write of a key decides whether it counts as quoted.
Round-Trip Guarantees
TOON guarantees lossless round-trip conversion:
Zero Dependencies
This node has zero production dependencies:
Note: There is another package called n8n-nodes-toon (non-scoped) that wraps the official @toon-format/toon library. This package (@tehw0lf/n8n-nodes-toon) implements the TOON specification directly, resulting in zero production dependencies and full control over the implementation.
Troubleshooting
Issue: “Input must be a string” error
Cause: TOON to JSON operation expects string input.
Solution: Ensure input field contains TOON text, not a JSON object.
Issue: Strict mode validation errors
Cause: TOON data doesn’t match expected structure.
Solution: Fix the TOON data. Disabling strict mode only relaxes count mismatches and the other recoveries listed under Strict Mode (including the Path Expansion conflict recovery); every other error still applies.
Issue: Key folding conflicts
Cause: Both user.name and user keys exist in same object.
Solution: Use keyFolding: "safe" which only folds when safe, or disable key folding.
Issue: Round-trip doesn’t match exactly
Cause: TOON normalizes data (e.g., -0 → 0, sorts object keys).
Solution: This is expected — TOON preserves semantic meaning, not exact formatting.
Automated Monitoring
This repository includes automated workflows for continuous monitoring:
Specification Monitoring
Monitors the official TOON specification for updates:
toonSpecVersion in package.json against the upstream GitHub Releases APIWhen a specification update is detected, the workflow:
1. Creates a labeled issue (spec-update, enhancement) with version details
2. Includes a diff summary showing the changes
3. Provides links to the official specification
4. Avoids duplicate issues for the same version
See .github/workflows/monitor-spec.yml for implementation details.
Security Monitoring
Scans the source and the build artifacts for known vulnerabilities. The workflow calls the reusable workflows security-scan-source.yml and security-scan-artifacts.yml from tehw0lf/workflows and does not build or publish anything:
auto, p/security-audit, p/owasp-top-ten, p/ci, p/nodejs and p/typescript rule setsnpm audit on production dependencies, failing at severity criticalbuild artifact of the latest successful CI run triggered by a push to main (downloaded, not rebuilt); the run fails when no such artifact existsOn failure of a scheduled or manual run:
1. A failed source scan opens one issue in this repository, updates it on later failures and closes it when a later run passes
2. When npm audit fails and npm audit fix changes package-lock.json, a pull request with the fix is opened or updated
See DEVELOPMENT.md for the full behavior and .github/workflows/security-scan.yml for implementation details.
Resources
License
MIT © tehw0lf
Author
tehw0lf
Contributing
Contributions are welcome! Please open an issue or pull request on GitHub.
—
Note: This node implements the TOON Specification v4.4. See SPEC.md for complete format documentation or visit the official spec repository.


