This page helps you get from zero to production-ready usage quickly.
Use TOON when you want structured data that is:
- smaller and easier to read than JSON
- still reversible back into arrays with
decode() - useful for prompts, logs, fixtures, and internal review flows
If your use case is external API transport, JSON should still be your default.
composer require sbsaga/toonLaravel package discovery registers provider and facade automatically.
Optional: publish config.
php artisan vendor:publish --provider="Sbsaga\Toon\ToonServiceProvider" --tag=configDrop this in a route or tinker session:
use Illuminate\Support\Facades\Route;
use Sbsaga\Toon\Facades\Toon;
Route::get('/toon-demo', function () {
$payload = [
'project' => 'TOON',
'users' => [
['id' => 1, 'name' => 'Alice', 'active' => true],
['id' => 2, 'name' => 'Bob', 'active' => false],
],
];
$encoded = Toon::encode($payload);
$decoded = Toon::decode($encoded);
return response()->json([
'toon' => $encoded,
'decoded' => $decoded,
]);
});Typical encoded output:
project: TOON
users:
items[2]{id,name,active}:
1,Alice,true
2,Bob,false
How to read it:
project: TOONis a simple key/value pairusers:starts a nested blockitems[2]{...}is a table with 2 rows and named columns- each row contains the values for that column order
use Sbsaga\Toon\Facades\Toon;
$toon = Toon::encode($payload); // array/json/scalar -> TOON string
$data = Toon::decode($toon); // TOON string -> array
$stats = Toon::estimateTokens($toon); // quick rough token estimate
$diff = Toon::diff($payload); // JSON-vs-TOON size comparisonGlobal helpers are also available:
$toon = toon_encode($payload);
$data = toon_decode($toon);
$diff = toon_diff($payload);Default mode is legacy, which keeps old behavior safer for existing users.
// config/toon.php
'compatibility_mode' => 'legacy',Use modern for new projects or controlled migrations:
// config/toon.php
'compatibility_mode' => 'modern',Use replacers to remove sensitive fields before TOON encoding.
use Sbsaga\Toon\Facades\Toon;
$safeToon = Toon::encodeWith($payload, function (array $path, string|int|null $key, mixed $value) {
if (in_array($key, ['password', 'token', 'api_key'], true)) {
return Toon::skip();
}
if ($key === 'email') {
return '[redacted]';
}
return $value;
});Helper version:
$safeToon = toon_encode_with($payload, function (array $path, string|int|null $key, mixed $value) {
return $key === 'debug' ? \Sbsaga\Toon\Toon::skip() : $value;
});If you want line-based processing:
use Sbsaga\Toon\Facades\Toon;
$lines = Toon::encodeLines($payload); // Generator<string>
$decoded = Toon::decodeFromLines($lines); // arrayHelper:
$lines = toon_encode_lines($payload); // array of linesBasic encode/decode:
php artisan toon:convert storage/app/payload.json --encode
php artisan toon:convert storage/app/payload.toon --decode --prettyExplicit direction and stats:
php artisan toon:convert storage/app/payload.data --from=json --to=toon --statsOne-off runtime overrides:
php artisan toon:convert storage/app/payload.json --encode --mode=modern --delimiter=pipeStrict validation for decode:
php artisan toon:convert storage/app/payload.toon --decode --strict- Keep
compatibility_mode=legacyfor initial upgrade rollout. - Add at least one encode/decode round-trip test for your critical payloads.
- Add a replacer for sensitive fields before logs/prompts.
- Enable strict decoding where malformed input must fail fast.
- Roll modern mode only after downstream consumers are verified.
- Using TOON as a direct replacement for public API JSON payloads
- Enabling modern mode in production without contract checks
- Logging raw sensitive payloads without replacer redaction
- Assuming token savings for very small payloads without measuring

