python-toon
Token-Oriented Object Notation for Python
A compact data format optimized for transmitting structured information to Large Language Models (LLMs) with 30-60% fewer tokens than JSON.
What is TOON?
TOON (Token-Oriented Object Notation) combines YAML's indentation-based structure for nested objects and CSV's tabular format for uniform data rows, optimized specifically for token efficiency in LLM contexts.
This is a faithful Python port of the original TOON TypeScript library by Johann Schopplich, maintaining 100% output compatibility with the official TOON specification.
Key Features
- 30-60% token reduction compared to standard JSON
- Minimal syntax: Eliminates redundant punctuation (braces, brackets, most quotes)
- Tabular arrays: CSV-like row format for uniform object collections
- Explicit metadata: Array length indicators
[N]for validation - LLM-friendly: Maintains semantic clarity while reducing token count
- 100% compatible with original TypeScript implementation
Installation
pip install python-toon
Quick Start
from toon import encode
# Simple object
data = {"name": "Alice", "age": 30}
print(encode(data))
# Output:
# name: Alice
# age: 30
# Tabular array (uniform objects)
users = [
{"id": 1, "name": "Alice", "age": 30},
{"id": 2, "name": "Bob", "age": 25},
{"id": 3, "name": "Charlie", "age": 35},
]
print(encode(users))
# Output:
# [3,]{id,name,age}:
# 1,Alice,30
# 2,Bob,25
# 3,Charlie,35
# Complex nested structure
data = {
"metadata": {"version": 1, "author": "test"},
"items": [
{"id": 1, "name": "Item1"},
{"id": 2, "name": "Item2"},
],
"tags": ["alpha", "beta", "gamma"],
}
print(encode(data))
# Output:
# metadata:
# version: 1
# author: test
# items[2,]{id,name}:
# 1,Item1
# 2,Item2
# tags[3]: alpha,beta,gamma
API Reference
encode(value, options=None)
Converts a Python value to TOON format.
Parameters:
value(Any): JSON-serializable value to encodeoptions(dict, optional): Encoding options
Returns: str - TOON-formatted string
Encoding Options
from toon import encode
encode(data, {
"indent": 2, # Spaces per indentation level (default: 2)
"delimiter": ",", # Delimiter for arrays: "," | "\t" | "|" (default: ",")
"lengthMarker": "#" # Optional marker prefix: "#" | False (default: False)
})
Delimiter Options
You can use string literals directly:
data = [1, 2, 3, 4, 5]
# Comma (default)
print(encode(data))
# [5]: 1,2,3,4,5
# Tab
print(encode(data, {"delimiter": "\t"}))
# [5 ]: 1 2 3 4 5
# Pipe
print(encode(data, {"delimiter": "|"}))
# [5|]: 1|2|3|4|5
Or use the string keys:
encode(data, {"delimiter": "comma"}) # Default
encode(data, {"delimiter": "tab"}) # Tab-separated
encode(data, {"delimiter": "pipe"}) # Pipe-separated
Length Markers
Add the # prefix to array length indicators:
users = [
{"id": 1, "name": "Alice"},
{"id": 2, "name": "Bob"},
]
# Without marker (default)
print(encode(users))
# [2,]{id,name}:
# 1,Alice
# 2,Bob
# With marker
print(encode(users, {"lengthMarker": "#"}))
# [#2,]{id,name}:
# 1,Alice
# 2,Bob
Format Rules
Objects
Key-value pairs with primitives or nested structures:
{"name": "Alice", "age": 30}
# =>
# name: Alice
# age: 30
Primitive Arrays
Arrays always include length [N]:
[1, 2, 3, 4, 5]
# => [5]: 1,2,3,4,5
["alpha", "beta", "gamma"]
# => [3]: alpha,beta,gamma
Tabular Arrays
Uniform objects with identical primitive-only fields use CSV-like format:
[
{"id": 1, "name": "Alice"},
{"id": 2, "name": "Bob"},
]
# =>
# [2,]{id,name}:
# 1,Alice
# 2,Bob
Note: The delimiter appears in the length bracket [2,] for tabular arrays.
Mixed Arrays
Non-uniform data using list format with - markers:
[{"name": "Alice"}, 42, "hello"]
# =>
# [3]:
# - name: Alice
# - 42
# - hello
Array Length Format
The length bracket format depends on the array type:
Tabular arrays (with fields):
- Delimiter always shown:
[2,]{fields}:or[2|]{fields}:or[2\t]{fields}:
Primitive arrays (no fields):
- Comma:
[3]:(delimiter hidden) - Other:
[3|]:or[3\t]:(delimiter shown)
Quoting Rules
Strings are quoted only when necessary (following the TOON specification):
- Empty strings
- Keywords:
null,true,false - Numeric strings:
42,-3.14 - Leading or trailing whitespace
- Contains structural characters:
:,[,],{,},-," - Contains current delimiter (
,,|, or tab) - Contains control characters (newline, carriage return, tab, backslash)
"hello" # => hello (no quotes)
"hello world" # => hello world (internal spaces OK)
" hello" # => " hello" (leading space requires quotes)
"null" # => "null" (keyword)
"42" # => "42" (looks like number)
"" # => "" (empty)
Type Conversions
Non-JSON types are normalized automatically:
- Numbers: Decimal form (no scientific notation)
- Dates/DateTime: ISO 8601 strings (quoted)
- Decimal: Converted to float
- Infinity/NaN: Converted to
null - Functions/Callables: Converted to
null - -0: Normalized to
0
LLM Integration Best Practices
When using TOON with LLMs:
-
Wrap in code blocks for clarity:
```toon name: Alice age: 30 ```
-
Instruct the model about the format:
"Respond using TOON format (Token-Oriented Object Notation). Use
key: valuesyntax, indentation for nesting, and tabular format[N,]{fields}:for uniform arrays." -
Leverage length markers for validation:
encode(data, {"lengthMarker": "#"})
Tell the model: "Array lengths are marked with
[#N]. Ensure your response matches these counts." -
Acknowledge tokenizer variance: Token savings depend on the specific tokenizer and model being used.
Token Efficiency Example
import json
from toon import encode
data = {
"users": [
{"id": 1, "name": "Alice", "age": 30, "active": True},
{"id": 2, "name": "Bob", "age": 25, "active": True},
{"id": 3, "name": "Charlie", "age": 35, "active": False},
]
}
json_str = json.dumps(data)
toon_str = encode(data)
print(f"JSON: {len(json_str)} characters")
print(f"TOON: {len(toon_str)} characters")
print(f"Reduction: {100 * (1 - len(toon_str) / len(json_str)):.1f}%")
# Output:
# JSON: 177 characters
# TOON: 85 characters
# Reduction: 52.0%
JSON output:
{"users": [{"id": 1, "name": "Alice", "age": 30, "active": true}, {"id": 2, "name": "Bob", "age": 25, "active": true}, {"id": 3, "name": "Charlie", "age": 35, "active": false}]}
TOON output:
users[3,]{id,name,age,active}:
1,Alice,30,true
2,Bob,25,true
3,Charlie,35,false
Development
Setup
# Clone the repository
git clone https://github.com/xaviviro/python-toon.git
cd python-toon
# Create virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install in development mode
pip install -e .
# Install development dependencies
pip install -r requirements-dev.txt
Running Tests
# Run all tests
pytest
# Run with coverage
pytest --cov=pytoon --cov-report=term
# Run original compatibility tests
python test_original_cases.py
Type Checking
mypy src/pytoon
Linting
ruff check src/pytoon tests
Credits
This project is a Python implementation of the original TOON format created by Johann Schopplich.
Original TOON (TypeScript): MIT License © 2025-PRESENT Johann Schopplich
python-toon (Python port): Developed by Xavi Vinaixa
License
MIT License - see LICENSE file for details
Related
- Original TOON (TypeScript) - The original implementation
- TOON Format Specification (SPEC.md) - Official v1 specification with normative encoding rules
- TOON README - Format overview and examples
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
When contributing, please:
- Run
python test_original_cases.pyto ensure 100% compatibility with the original - Add tests for new features
- Update documentation as needed
Support
For bugs and feature requests, please open an issue.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file python_toon-0.1.1.tar.gz.
File metadata
- Download URL: python_toon-0.1.1.tar.gz
- Upload date:
- Size: 15.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3974182d021b0ef4f24112bee7c2ca42686bab790524cc89c2cddbfff7145a02
|
|
| MD5 |
c57d3a9df2f557e471edc02ee9ed923d
|
|
| BLAKE2b-256 |
2741c00266236b245076cce78ee83d890b2ac83cbaf9b382e3c48bfa4cba2a19
|
Provenance
The following attestation bundles were made for python_toon-0.1.1.tar.gz:
Publisher:
publish.yml on xaviviro/python-toon
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
python_toon-0.1.1.tar.gz -
Subject digest:
3974182d021b0ef4f24112bee7c2ca42686bab790524cc89c2cddbfff7145a02 - Sigstore transparency entry: 653683017
- Sigstore integration time:
-
Permalink:
xaviviro/python-toon@fb0f50645e7f231119d6299e030701ef45a37115 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/xaviviro
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@fb0f50645e7f231119d6299e030701ef45a37115 -
Trigger Event:
release
-
Statement type:
File details
Details for the file python_toon-0.1.1-py3-none-any.whl.
File metadata
- Download URL: python_toon-0.1.1-py3-none-any.whl
- Upload date:
- Size: 12.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bbe5f34a1742716d0adf14d7c36f06db6aab850d0a61263d6e93bd4aeb8fa728
|
|
| MD5 |
bc3544b9af9e495063f1c4977d021588
|
|
| BLAKE2b-256 |
56edebf8b26882c949a7d8053b892d83fdf2186bef0b84bf47be7e3b4d588564
|
Provenance
The following attestation bundles were made for python_toon-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on xaviviro/python-toon
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
python_toon-0.1.1-py3-none-any.whl -
Subject digest:
bbe5f34a1742716d0adf14d7c36f06db6aab850d0a61263d6e93bd4aeb8fa728 - Sigstore transparency entry: 653683032
- Sigstore integration time:
-
Permalink:
xaviviro/python-toon@fb0f50645e7f231119d6299e030701ef45a37115 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/xaviviro
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@fb0f50645e7f231119d6299e030701ef45a37115 -
Trigger Event:
release
-
Statement type: