{
"loading": true
"progress": ...
}
JSON Formatters Pro
Data Formats

TOON Syntax Reference: Complete Specification and Examples

📅 December 10, 2025 ⏱️ 3 min read 👁️ 5 views 🏷️ Data Formats

This is a complete reference for TOON (Token-Oriented Object Notation) syntax. Use this guide to understand every aspect of the format.

File Format Basics

  • File extension: .toon
  • Media type: text/toon
  • Encoding: UTF-8 (always)
  • Line endings: LF or CRLF

Primitive Values

Strings

# Unquoted strings (preferred when possible)
name: John Doe
city: New York

# Quoted strings (required for special characters)
description: "Hello, World!"
multiline: "Line 1\nLine 2"

Numbers

# Integers
count: 42
negative: -17

# Floating point
price: 29.99
scientific: 1.5e10

Booleans and Null

active: true
verified: false
deletedAt: null

Objects

Simple Objects

# Key-value pairs with colon
name: Alice
age: 30
email: alice@example.com

Nested Objects

# Use indentation for nesting (2 spaces recommended)
user
  name: Bob
  profile
    avatar: url
    bio: Developer
  settings
    theme: dark
    notifications: true

Arrays

Tabular Arrays (Uniform Objects)

When all array items are objects with the same keys, use tabular format:

# Syntax: name [count] {field1, field2, ...}
# Followed by comma-separated values, one row per item

users [3] {id, name, email, active}
1, Alice, alice@example.com, true
2, Bob, bob@example.com, true
3, Charlie, charlie@example.com, false

Simple Arrays (Primitives)

# Non-object arrays use dash prefix
tags [4]
- javascript
- python
- rust
- go

Empty Arrays

noItems [0]

Quoting Rules

Condition Quoting Required? Example
Simple alphanumeric No name: John
Contains spaces Only if leading/trailing city: New York
Contains comma Yes desc: "Hello, World"
Contains colon Yes time: "12:30:00"
Empty string Yes empty: ""

Parser Implementation

class ToonParser {
  parse(toonText) {
    const lines = toonText.split('\n').filter(l => !l.trim().startsWith('#'));
    return this.parseLines(lines, 0).value;
  }
  
  parseLines(lines, startIndex) {
    const result = {};
    let i = startIndex;
    const baseIndent = this.getIndent(lines[i] || '');
    
    while (i < lines.length) {
      const line = lines[i];
      const indent = this.getIndent(line);
      const content = line.trim();
      
      if (!content || indent < baseIndent) break;
      if (indent > baseIndent) { i++; continue; }
      
      // Check for tabular array
      const tabularMatch = content.match(/^(\w+)\s*\[(\d+)\]\s*\{([^}]+)\}/);
      if (tabularMatch) {
        const key = tabularMatch[1];
        const count = parseInt(tabularMatch[2]);
        const fields = tabularMatch[3].split(',').map(f => f.trim());
        result[key] = this.parseTabular(lines, i + 1, count, fields);
        i += count + 1;
        continue;
      }
      
      // Key-value pair
      const kvMatch = content.match(/^(\w+):\s*(.+)?$/);
      if (kvMatch) {
        const key = kvMatch[1];
        const value = kvMatch[2];
        result[key] = this.parseValue(value);
        i++;
        continue;
      }
      
      i++;
    }
    
    return { value: result, nextIndex: i };
  }
  
  parseTabular(lines, startIndex, count, fields) {
    const items = [];
    for (let i = 0; i < count && startIndex + i < lines.length; i++) {
      const values = lines[startIndex + i].split(',').map(v => v.trim());
      const item = {};
      fields.forEach((field, idx) => {
        item[field] = this.parseValue(values[idx]);
      });
      items.push(item);
    }
    return items;
  }
  
  parseValue(val) {
    if (val === undefined || val === '') return null;
    if (val === 'true') return true;
    if (val === 'false') return false;
    if (val === 'null') return null;
    if (!isNaN(val) && val !== '') return Number(val);
    return val.replace(/^"|"$/g, '');
  }
  
  getIndent(line) {
    const match = line.match(/^(\s*)/);
    return match ? match[1].length : 0;
  }
}

// Usage
const parser = new ToonParser();
const toonData = 'users [2] {name, age}\nAlice, 30\nBob, 25';

console.log(parser.parse(toonData));
// { users: [{name: "Alice", age: 30}, {name: "Bob", age: 25}] }

Quick Reference Card

# TOON Quick Reference

# Objects (indentation-based)
key: value
nested
  child: value

# Tabular Arrays (uniform objects)
arrayName [N] {field1, field2}
val1, val2
val3, val4

# Simple Arrays
listName [N]
- item1
- item2

# Primitives
string: hello world
quoted: "has, comma"
number: 42
float: 3.14
bool: true
nothing: null

# Comments
# This is a comment

Validation Checklist

  1. Array count matches actual items
  2. Field count matches values per row
  3. Consistent indentation (2 spaces)
  4. Special characters are quoted
  5. UTF-8 encoding

🔧 Try Our Free TOON Converter

Convert your JSON to TOON format instantly and see your token savings in real-time!

⚡ Open TOON Converter
🏷️ Tags:
toon syntax specification reference documentation format rules

📚 Related Articles