toon-format
toon-python
Python

๐Ÿ Community-driven Python implementation of TOON

Last updated Jul 1, 2026
740
Stars
58
Forks
25
Issues
+3
Stars/day
Attention Score
60
Language breakdown
Python 100.0%
โ–ธ Files click to expand
README

TOON Format for Python

Tests Python Versions

โš ๏ธ Beta Status (v0.9.x): This library is in active development and working towards spec compliance. Beta published to PyPI. API may change before 1.0.0 release.

Compact, human-readable serialization format for LLM contexts with 30-60% token reduction vs JSON. Combines YAML-like indentation with CSV-like tabular arrays. Working towards full compatibility with the official TOON specification.

Key Features: Minimal syntax โ€ข Tabular arrays for uniform data โ€ข Array length validation โ€ข Python 3.8+ โ€ข Comprehensive test coverage.

# Beta published to PyPI - install from source:
git clone https://github.com/toon-format/toon-python.git
cd toon-python
uv sync

Or install directly from GitHub:

pip install git+https://github.com/toon-format/toon-python.git

Quick Start

from toon_format import encode, decode

Simple object

encode({"name": "Alice", "age": 30})

name: Alice

age: 30

Tabular array (uniform objects)

encode([{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}])

[2,]{id,name}:

1,Alice

2,Bob

Decode back to Python

decode("items[2]: apple,banana")

{'items': ['apple', 'banana']}

CLI Usage

# Auto-detect format by extension
toon input.json -o output.toon      # Encode
toon data.toon -o output.json       # Decode
echo '{"x": 1}' | toon -            # Stdin/stdout

Options

toon data.json --encode --delimiter "\t" --length-marker toon data.toon --decode --no-strict --indent 4

Options: -e/--encode -d/--decode -o/--output --delimiter --indent --length-marker --no-strict

API Reference

encode(value, options=None) โ†’ str

encode({"id": 123}, {"delimiter": "\t", "indent": 4, "lengthMarker": "#"})

Options:

  • delimiter: "," (default), "\t", "|"
  • indent: Spaces per level (default: 2)
  • lengthMarker: "" (default) or "#" to prefix array lengths

decode(input_str, options=None) โ†’ Any

decode("id: 123", {"indent": 2, "strict": True})

Options:

  • indent: Expected indent size (default: 2)
  • strict: Validate syntax, lengths, delimiters (default: True)

Token Counting & Comparison

Measure token efficiency and compare formats:

from toonformat import estimatesavings, compareformats, counttokens

Measure savings

data = {"users": [{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}]} result = estimate_savings(data) print(f"Saves {result['savings_percent']:.1f}% tokens") # Saves 42.3% tokens

Visual comparison

print(compare_formats(data))

Format Comparison

โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€

Format Tokens Size (chars)

JSON 45 123

TOON 28 85

โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€

Savings: 17 tokens (37.8%)

Count tokens directly

toon_str = encode(data) tokens = counttokens(toonstr) # Uses tiktoken (gpt5/gpt5-mini)

Requires tiktoken: uv add tiktoken (benchmark features are optional)

Format Specification

| Type | Example Input | TOON Output | |------|---------------|-------------| | Object | {"name": "Alice", "age": 30} | name: Alice
age: 30 | | Primitive Array | [1, 2, 3] | [3]: 1,2,3 | | Tabular Array | [{"id": 1, "name": "A"}, {"id": 2, "name": "B"}] | [2,]{id,name}:
  1,A
  2,B | | Mixed Array | [{"x": 1}, 42, "hi"] | [3]:
  - x: 1
  - 42
  - hi |

Quoting: Only when necessary (empty, keywords, numeric strings, whitespace, structural chars, delimiters)

Type Normalization: Infinity/NaN/Functions โ†’ null โ€ข Decimal โ†’ float โ€ข datetime โ†’ ISO 8601 โ€ข -0 โ†’ 0

Pydantic Integration โ€“ (Structured TOON for LLM Outputs)

Adds a completely optional Pydantic integration via the [pydantic] extra.

pip install "toon-python[pydantic]"

Features

  • Schema: 50โ€“60 % smaller than modeljsonschema()
  • Zero JSON parsing errors
  • Works with Instructor, Outlines, Marvin, LangChain agents, etc.
  • Full Pydantic validation preserved

Usage After Release

from toon_format.pydantic import ToonPydanticModel

class User(ToonPydanticModel): name: str age: int email: str | None = None

Convert schema to TOON for LLM system prompts

schematoon = User.schemato_toon()

name:str,age:int,email:str|None

Parse LLM TOON output into validated Pydantic model

toon_output = "name:Ansar,age:25,email:ansar@example.com" user = User.modelvalidatetoon(toon_output)

user.name โ†’ "Ansar"

user.age โ†’ 25

user.email โ†’ "ansar@example.com"

Serialize a model instance back to TOON

toonstr = user.modeldump_toon()

Development

# Setup (requires uv: https://docs.astral.sh/uv/)
git clone https://github.com/toon-format/toon-python.git
cd toon-python
uv sync

Run tests (792 tests, 91% coverage, 85% enforced)

uv run pytest --cov=toon_format --cov-report=term

Code quality

uv run ruff check src/ tests/ # Lint uv run ruff format src/ tests/ # Format uv run mypy src/ # Type check

CI/CD: GitHub Actions โ€ข Python 3.8-3.14 โ€ข Coverage enforcement โ€ข PR coverage comments

Project Status & Roadmap

Following semantic versioning towards 1.0.0:

  • v0.8.x - Initial code set, tests, documentation โœ…
  • v0.9.x - Serializer improvements, spec compliance testing, publishing setup (current)
  • v1.0.0-rc.x - Release candidates for production readiness
  • v1.0.0 - First stable release with full spec compliance
See CONTRIBUTING.md for detailed guidelines.

Documentation

Contributors

License

MIT License โ€“ see LICENSE for details

ยฉ 2026 GitRepoTrend ยท toon-format/toon-python ยท Updated daily from GitHub