Skip to main content

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.

Tests PyPI Python Versions

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.

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 encode
  • options (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:

  • Keywords: null, true, false
  • Numeric strings: 42, -3.14
  • Contains spaces, tabs, newlines
  • Contains structural characters: :, ,, |, [, ], {, }, -
  • Contains current delimiter
  • Empty strings
"hello"        # => hello (no quotes)
"hello world"  # => "hello world" (has space)
"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:

  1. Wrap in code blocks for clarity:

    ```toon
    name: Alice
    age: 30
    ```
    
  2. Instruct the model about the format:

    "Respond using TOON format (Token-Oriented Object Notation). Use key: value syntax, indentation for nesting, and tabular format [N,]{fields}: for uniform arrays."

  3. Leverage length markers for validation:

    encode(data, {"lengthMarker": "#"})
    

    Tell the model: "Array lengths are marked with [#N]. Ensure your response matches these counts."

  4. 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

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

When contributing, please:

  • Run python test_original_cases.py to 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

python_toon-0.1.0.tar.gz (15.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

python_toon-0.1.0-py3-none-any.whl (12.6 kB view details)

Uploaded Python 3

File details

Details for the file python_toon-0.1.0.tar.gz.

File metadata

  • Download URL: python_toon-0.1.0.tar.gz
  • Upload date:
  • Size: 15.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for python_toon-0.1.0.tar.gz
Algorithm Hash digest
SHA256 6433d00fecd5e1b3a9654c0c5230278943fc9d93df1572dd0283f85bbd2a7d6a
MD5 aadc8511edba682d12b01ca800f9519a
BLAKE2b-256 3f90ae5564f4046ecbfd5df1cc38351da3e1f51101b8a7633f2b2f2dd9fd6fc4

See more details on using hashes here.

Provenance

The following attestation bundles were made for python_toon-0.1.0.tar.gz:

Publisher: publish.yml on xaviviro/python-toon

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file python_toon-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: python_toon-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 12.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for python_toon-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 96114bf2c2ca4922a89cb0ed1ef849089fa966a389461ef5c87e8c40dd3b4981
MD5 bb167872f0aebcdb072e1fbef4ca8787
BLAKE2b-256 5db08150a18b585c584d94627f21ea90794a40e870631d52cd2491c61338a1c7

See more details on using hashes here.

Provenance

The following attestation bundles were made for python_toon-0.1.0-py3-none-any.whl:

Publisher: publish.yml on xaviviro/python-toon

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page