A pure PHP implementation of TOON - A human-readable data serialization format.
This is a standalone PHP library with no dependencies. See https://github.com/toon-format/toon/blob/main/README.md for the original documentation that provide detailed information and benchmarks.
composer require robertgdev/php-toonuse RobertGDev\Toon\Toon;
use RobertGDev\Toon\Types\EncodeOptions;
// Simple encoding
$data = ['name' => 'Ada', 'age' => 30, 'active' => true];
$encoded = Toon::encode($data);
// Output: name: Ada\nage: 30\nactive: true
// With options
$options = new EncodeOptions(
indent: 4, // Number of spaces per indentation level
delimiter: "\t", // Delimiter for arrays (comma, tab, or pipe)
lengthMarker: '#' // Add # prefix to array lengths
);
$encoded = Toon::encode($data, $options);use RobertGDev\Toon\Toon;
use RobertGDev\Toon\Types\DecodeOptions;
// Simple decoding
$toonString = "name: Ada\nage: 30\nactive: true";
$decoded = Toon::decode($toonString);
// Output: ['name' => 'Ada', 'age' => 30, 'active' => true]
// With options
$options = new DecodeOptions(
indent: 4, // Number of spaces per indentation level
strict: false // Disable strict validation
);
$decoded = Toon::decode($toonString, $options);- Pure PHP 8.1+: No dependencies, works in any PHP project
- Primitives: Strings, numbers, booleans, null
- Objects: Nested key-value structures with dot notation support
- Arrays: Inline primitive arrays, tabular object arrays, and nested arrays
- Flexible Delimiters: Support for comma, tab, and pipe delimiters
- Strict Mode: Optional validation for array lengths and indentation
- Length Markers: Optional # prefix for array lengths
- Unicode Support: Full support for UTF-8 strings and emoji
Run tests using Pest:
composer testOr using PHPUnit directly:
./vendor/bin/pestUsing Associative Arrays:
$data = [
'name' => 'Ada Lovelace',
'born' => 1815,
'contributions' => ['mathematics', 'computing']
];
echo Toon::encode($data);Output:
name: Ada Lovelace
born: 1815
contributions[2]: mathematics,computing
Using StdClass (Recommended for clarity):
$data = new StdClass();
$data->name = 'Ada Lovelace';
$data->born = 1815;
$data->contributions = ['mathematics', 'computing'];
echo Toon::encode($data);Output (identical):
name: Ada Lovelace
born: 1815
contributions[2]: mathematics,computing
Using Associative Arrays:
$data = [
'user' => [
'id' => 123,
'profile' => [
'name' => 'Ada',
'email' => 'ada@example.com'
]
]
];
echo Toon::encode($data);Output:
user:
id: 123
profile:
name: Ada
email: ada@example.com
Using StdClass (Recommended for clarity):
$profile = new StdClass();
$profile->name = 'Ada';
$profile->email = 'ada@example.com';
$user = new StdClass();
$user->id = 123;
$user->profile = $profile;
$data = new StdClass();
$data->user = $user;
echo Toon::encode($data);Output (identical):
user:
id: 123
profile:
name: Ada
email: ada@example.com
$data = [
'products' => [
['id' => 1, 'name' => 'Widget', 'price' => 9.99],
['id' => 2, 'name' => 'Gadget', 'price' => 14.99],
]
];
echo Toon::encode($data);Output:
products[2]{id,name,price}:
1,Widget,9.99
2,Gadget,14.99
Encode PHP data to TOON format.
public static function encode(mixed $input, ?EncodeOptions $options = null): stringDecode TOON format to PHP data.
public static function decode(string $input, ?DecodeOptions $options = null): mixednew EncodeOptions(
int $indent = 2, // Spaces per indent level
string $delimiter = ',', // Array delimiter: ',', "\t", or '|'
string|false $lengthMarker = false // Use '#' or false
)new DecodeOptions(
int $indent = 2, // Spaces per indent level
bool $strict = true, // Enable strict validation
bool $objectsAsStdClass = false // Decode objects as StdClass
)PHP has a fundamental difference from JavaScript: empty arrays [] are ambiguous and can represent both empty objects {} and empty arrays [].
JavaScript Distinction:
const obj = {}; // Empty object
const arr = []; // Empty arrayPHP Ambiguity:
$both = []; // Could be object OR array!1. Using StdClass for Objects (Recommended)
To avoid ambiguity, use StdClass for objects:
$obj = new StdClass(); // Clearly an object
$arr = []; // Clearly an array2. Encoding Behavior
- StdClass objects → Always encoded as objects
- Sequential arrays (
[0 => 'a', 1 => 'b']) → Always encoded as arrays with[n]: - Associative arrays (
['key' => 'value']) → Encoded as objects withkey: - Empty
[]at root → Treated as empty object (returns'') - Empty
[]in object values → Detected by context based on semantic intent
3. Decoding Behavior
By default, objects decode to associative arrays:
$toon = "user:\n name: Ada";
$decoded = Toon::decode($toon);
// Result: ['user' => ['name' => 'Ada']]Enable objectsAsStdClass for perfect round-trips:
$options = new DecodeOptions(objectsAsStdClass: true);
$decoded = Toon::decode($toon, $options);
// Result: StdClass object with $decoded->user->name === 'Ada'✅ DO: Use StdClass for objects to avoid ambiguity
$user = new StdClass();
$user->name = 'Ada';✅ DO: Use sequential arrays for lists
$items = [1, 2, 3];✅ DO: Use objectsAsStdClass option for perfect encode/decode round-trips
$encoded = Toon::encode($stdClassObj);
$decoded = Toon::decode($encoded, new DecodeOptions(objectsAsStdClass: true));
// $decoded === $stdClassObj structure❌ AVOID: Mixing empty [] where object/array distinction matters
// Ambiguous - is 'data' an empty object or array?
$data = ['user' => [], 'items' => []];
// Clear - use StdClass for objects
$data = ['user' => new StdClass(), 'items' => []];