Compact, human-readable serialization format for LLM contexts with 30-60% token reduction vs JSON. Combines YAML-like indentation with CSV-like tabular arrays. Full compatibility with the official TOON specification.
Key Features: Minimal syntax β’ Tabular arrays for uniform data β’ Array length validation β’ Swift 6.0+ β’ Configurable delimiters β’ Key folding / Path expansion support β’ Linux compatible.
LLM tokens are expensive, and JSON is verbose. TOON saves tokens while remaining human-readable by using indentation for structure and a tabular format for uniform data:
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
For full details on TOON's design, benchmarks, and specification, see the TOON specification.
TOONEncoder conforms to TOON specification version 3.0 (2025-11-24)
and implements the following features:
- Canonical number formatting (no trailing zeros, no leading zeros except
0;-0normalized to0) - Correct escape sequences for strings (
\\,\",\n,\r,\t) - Three delimiter types: comma (default), tab, pipe
- Array length validation
- Object key order preservation
- Array order preservation
- Tabular format for uniform object arrays
- Inline format for primitive arrays
- Expanded list format for nested structures
- Key folding to collapse single-key object chains into dotted paths
- Configurable flatten depth to limit the depth of key folding
- Collision avoidance so folded keys never collide with existing sibling keys
TOONDecoder conforms to TOON specification version 3.0 (2025-11-24)
and implements the following features:
- Correct escape sequence parsing (
\\,\",\n,\r,\t) - Three delimiter types: comma (default), tab, pipe
- Array length validation
- Tabular format parsing with field headers
- Inline format for primitive arrays
- Expanded list format for nested structures
- Path expansion to unfold dotted keys into nested objects (inverse of key folding)
- Detailed error reporting with line numbers
- Configurable decoding limits for security
- Swift 6.0+ / Xcode 16+
- iOS 13.0+ / macOS 10.15+ / watchOS 6.0+ / tvOS 13.0+ / visionOS 1.0+ / Linux
Add the following to your Package.swift file:
dependencies: [
.package(url: "https://github.com/toon-format/toon-swift.git", from: "0.3.0")
]Then add the dependency to your target:
.target(name: "YourTarget", dependencies: ["ToonFormat"])import ToonFormat
struct User: Codable {
let id: Int
let name: String
let tags: [String]
let active: Bool
}
// Encoding
let user = User(
id: 123,
name: "Ada",
tags: ["reading", "gaming"],
active: true
)
let encoder = TOONEncoder()
let data = try encoder.encode(user)
print(String(data: data, encoding: .utf8)!)
// id: 123
// name: Ada
// tags[2]: reading,gaming
// active: true
// Decoding
let decoder = TOONDecoder()
let decoded = try decoder.decode(User.self, from: data)
print(decoded.name) // "Ada"Use tab or pipe delimiters for additional token savings:
struct Item: Codable {
let sku: String
let name: String
let qty: Int
let price: Double
}
let items = [
Item(sku: "A1", name: "Widget", qty: 2, price: 9.99),
Item(sku: "B2", name: "Gadget", qty: 1, price: 14.5)
]
let encoder = TOONEncoder()
encoder.delimiter = .tab // or .pipe
let data = try encoder.encode(["items": items])Output with tab delimiter:
items[2 ]{sku name qty price}:
A1 Widget 2 9.99
B2 Gadget 1 14.5
Output with pipe delimiter:
items[2|]{sku|name|qty|price}:
A1|Widget|2|9.99
B2|Gadget|1|14.5
Arrays of objects with identical primitive fields use an efficient tabular format:
struct Item: Codable {
let sku: String
let qty: Int
let price: Double
}
let items = [
Item(sku: "A1", qty: 2, price: 9.99),
Item(sku: "B2", qty: 1, price: 14.5)
]
let encoder = TOONEncoder()
let data = try encoder.encode(["items": items])Output:
items[2]{sku,qty,price}:
A1,2,9.99
B2,1,14.5
For arrays containing primitive inner arrays:
let pairs = [[1, 2], [3, 4]]
let encoder = TOONEncoder()
let data = try encoder.encode(["pairs": pairs])Output:
pairs[2]:
- [2]: 1,2
- [2]: 3,4
Key folding collapses single-key nested objects into dotted paths, reducing indentation and token count:
struct Config: Codable {
struct Database: Codable {
struct Connection: Codable {
let host: String
let port: Int
}
let connection: Connection
}
let database: Database
}
let config = Config(
database: .init(
connection: .init(host: "localhost", port: 5432)
)
)
let encoder = TOONEncoder()
encoder.keyFolding = .safe
let data = try encoder.encode(config)Without key folding:
database:
connection:
host: localhost
port: 5432
Output with key folding (encoder.keyFolding = .safe):
database.connection:
host: localhost
port: 5432
Protect against malicious or malformed input:
let decoder = TOONDecoder()
decoder.limits = TOONDecoder.DecodingLimits(
maxInputSize: 1024 * 1024, // 1 MB
maxDepth: 64,
maxObjectKeys: 1000,
maxArrayLength: 10000
)Check the supported TOON specification version:
print(toonSpecVersion) // "3.0"Contributions are welcome! Please read our Contributing Guide for details on how to get started, coding standards, and the process for submitting pull requests.
Before contributing, please review:
This project follows the Contributor Covenant Code of Conduct. By participating, you are expected to uphold this code. Please report unacceptable behavior to [email protected].
This library implements TOON specification version 3.0 (2025-11-24) with full encoding and decoding support.
See CONTRIBUTING.md for detailed guidelines.
- π TOON Spec - Official specification
- π Issues - Bug reports and features
- π€ Contributing - Contribution guidelines
MIT License β see LICENSE.md for details