PHPackages                             mountsoftware/symfony-toon-serializer - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. mountsoftware/symfony-toon-serializer

ActiveLibrary

mountsoftware/symfony-toon-serializer
=====================================

Symfony Serializer integration for TOON (Token-Oriented Object Notation) on top of helgesverre/toon

v1.0.0(4mo ago)0342↓100%MITPHPPHP &gt;=8.1CI passing

Since Nov 19Pushed 4mo agoCompare

[ Source](https://github.com/mount-software/symfony-toon-serializer)[ Packagist](https://packagist.org/packages/mountsoftware/symfony-toon-serializer)[ RSS](/packages/mountsoftware-symfony-toon-serializer/feed)WikiDiscussions main Synced today

READMEChangelog (1)Dependencies (5)Versions (3)Used By (0)

Symfony TOON Serializer
=======================

[](#symfony-toon-serializer)

[![CI/CD](https://github.com/mountsoftware/symfony-toon-serializer/actions/workflows/ci.yml/badge.svg)](https://github.com/mountsoftware/symfony-toon-serializer/actions)[![Latest Stable Version](https://camo.githubusercontent.com/214bb5e7c610008e6f55859ad3d749c1bed1304442ebc2d907132ca4c3f2f19e/68747470733a2f2f706f7365722e707567782e6f72672f6d6f756e74736f6674776172652f73796d666f6e792d746f6f6e2d73657269616c697a65722f762f737461626c65)](https://packagist.org/packages/mountsoftware/symfony-toon-serializer)[![Total Downloads](https://camo.githubusercontent.com/6b72cdf5e1ef744785f311b01206a1959fd5c8cc600cf5c7654e269f05f7e1e2/68747470733a2f2f706f7365722e707567782e6f72672f6d6f756e74736f6674776172652f73796d666f6e792d746f6f6e2d73657269616c697a65722f646f776e6c6f616473)](https://packagist.org/packages/mountsoftware/symfony-toon-serializer)[![License](https://camo.githubusercontent.com/5de3e9f263250291c5be69635fab13e66b30c25586c0ae0afb24649b7ab09d0a/68747470733a2f2f706f7365722e707567782e6f72672f6d6f756e74736f6674776172652f73796d666f6e792d746f6f6e2d73657269616c697a65722f6c6963656e7365)](https://packagist.org/packages/mountsoftware/symfony-toon-serializer)![PHP Version](https://camo.githubusercontent.com/6518db1335bf20fdff07253dc6d6d0cec955b5fb6a8ef1382ac6d73687ecc07f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d253345253344382e312d626c7565)

A Symfony Serializer integration for **TOON** (Token-Oriented Object Notation) format, built on top of the [`helgesverre/toon`](https://github.com/HelgeSverre/toon) library.

TOON is a compact, human-readable data serialization format optimized for LLM contexts and token efficiency.

Installation
------------

[](#installation)

Install via Composer:

```
composer require mountsoftware/symfony-toon-serializer
```

Requirements
------------

[](#requirements)

- PHP 8.1 or higher
- Symfony Serializer ^6.4 or ^7.0
- helgesverre/toon ^1.0

Features
--------

[](#features)

- 🔌 **Drop-in integration** with Symfony Serializer component
- 📦 **Format identifier**: `toon`
- ⚙️ **Configurable options**: delimiters, strict mode, indentation
- ✅ **Option validation**: Early error detection with clear exceptions
- 🎨 **Symfony conventions**: Namespaced context options following best practices
- 🔒 **Type-safe constants**: Use `ToonOptions` for autocomplete &amp; validation
- 🧪 **Comprehensive test suite**: 76 tests covering all scenarios
- 📝 **Standalone service**: Use TOON without the full serializer
- 🎯 **Thin wrapper**: Delegates all TOON logic to the proven `helgesverre/toon` library

Quick Start
-----------

[](#quick-start)

### Using with Symfony Serializer

[](#using-with-symfony-serializer)

```
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use MountSoftware\SymfonyToonSerializer\Encoder\ToonEncoder;

$serializer = new Serializer(
    [new ObjectNormalizer()],
    [new ToonEncoder()]
);

// Serialize to TOON
$data = [
    'id' => 123,
    'name' => 'Alice',
    'active' => true,
];

$toon = $serializer->serialize($data, 'toon');
// Output:
// id: 123
// name: Alice
// active: true

// Deserialize from TOON
$decoded = $serializer->deserialize($toon, YourClass::class, 'toon');
```

### Using the Standalone Service

[](#using-the-standalone-service)

```
use MountSoftware\SymfonyToonSerializer\ToonService;

$toonService = new ToonService();

// Encode
$toon = $toonService->encode([
    'user' => [
        'name' => 'Bob',
        'age' => 30,
    ],
]);

// Decode
$data = $toonService->decode($toon);
```

Configuration
-------------

[](#configuration)

### Context Options

[](#context-options)

Following Symfony conventions, options must be namespaced under `toon_options`:

```
use MountSoftware\SymfonyToonSerializer\ToonOptions;

$toon = $serializer->serialize($data, 'toon', [
    'toon_options' => [
        ToonOptions::DELIMITER => ToonOptions::DELIMITER_TAB,
        ToonOptions::STRICT => true,
        ToonOptions::INDENT => 4,
    ],
]);
```

This prevents conflicts with other encoders and follows Symfony best practices.

### Using Option Constants

[](#using-option-constants)

The `ToonOptions` class provides constants for type safety:

```
use MountSoftware\SymfonyToonSerializer\ToonOptions;

// Option keys
ToonOptions::DELIMITER
ToonOptions::INDENT
ToonOptions::STRICT
ToonOptions::LENGTH_MARKER

// Delimiter values
ToonOptions::DELIMITER_COMMA  // ','
ToonOptions::DELIMITER_TAB    // "\t"
ToonOptions::DELIMITER_PIPE   // '|'
```

### Available Options

[](#available-options)

#### Encoding Options

[](#encoding-options)

- **`delimiter`** (string, default: `','`): Field delimiter for tabular data
    - Comma: `','`
    - Tab: `"\t"`
    - Pipe: `'|'`
- **`indent`** (int, default: `2`): Number of spaces for indentation
- **`lengthMarker`** (string|false, default: `false`): Prefix for array length markers (use `'#'` or `false`)

#### Decoding Options

[](#decoding-options)

- **`strict`** (bool, default: `true`): Enable strict mode validation
    - In strict mode: Validates array lengths, column counts, indentation
    - In lenient mode: More forgiving parsing
- **`indent`** (int, default: `2`): Expected indentation level

### Default Options

[](#default-options)

Set default options for the encoder:

```
$encoder = new ToonEncoder([
    'delimiter' => '|',
    'indent' => 4,
    'strict' => false,
]);
```

Context options override default options:

```
// Uses pipe delimiter (from defaults)
$toon1 = $encoder->encode($data, 'toon');

// Uses tab delimiter (from context)
$toon2 = $encoder->encode($data, 'toon', [
    'toon_options' => ['delimiter' => "\t"],
]);
```

### Option Validation

[](#option-validation)

The library validates all options and throws `InvalidArgumentException` for invalid values:

```
// Invalid delimiter - throws exception
$serializer->serialize($data, 'toon', [
    'toon_options' => [
        'delimiter' => ';',  // Only ',', "\t", '|' are valid
    ],
]);

// Invalid indent - throws exception
$serializer->serialize($data, 'toon', [
    'toon_options' => [
        'indent' => -1,  // Must be >= 0
    ],
]);

// Invalid strict mode - throws exception
$encoder->decode($toon, 'toon', [
    'toon_options' => [
        'strict' => 'true',  // Must be boolean, not string
    ],
]);
```

This prevents silent failures and catches configuration errors early.

Examples
--------

[](#examples)

### Simple Object

[](#simple-object)

```
$data = [
    'id' => 123,
    'name' => 'Ada',
    'active' => true,
];

$toon = $serializer->serialize($data, 'toon');
```

Output:

```
id: 123
name: Ada
active: true

```

### Nested Object

[](#nested-object)

```
$data = [
    'user' => [
        'id' => 123,
        'name' => 'Ada',
        'meta' => [
            'active' => true,
            'score' => 9.5,
        ],
    ],
];
```

Output:

```
user:
  id: 123
  name: Ada
  meta:
    active: true
    score: 9.5

```

### Arrays of Primitives

[](#arrays-of-primitives)

```
$data = [
    'tags' => ['admin', 'ops', 'dev'],
];
```

Output:

```
tags[3]: admin,ops,dev

```

### Tabular Data

[](#tabular-data)

```
$data = [
    'users' => [
        ['id' => 1, 'name' => 'Alice', 'role' => 'admin'],
        ['id' => 2, 'name' => 'Bob', 'role' => 'user'],
    ],
];
```

Output:

```
users[2]{id,name,role}:
  1,Alice,admin
  2,Bob,user

```

### Tab-Delimited Data

[](#tab-delimited-data)

```
$data = [
    'items' => [
        ['sku' => 'A1', 'name' => 'Widget', 'qty' => 2],
        ['sku' => 'B2', 'name' => 'Gadget', 'qty' => 1],
    ],
];

$toon = $serializer->serialize($data, 'toon', [
    'toon_options' => ['delimiter' => "\t"],
]);
```

Output:

```
items[2	]{sku	name	qty}:
  A1	Widget	2
  B2	Gadget	1

```

### Pipe-Delimited Data

[](#pipe-delimited-data)

```
$data = [
    'products' => [
        ['id' => 1, 'name' => 'Item A'],
        ['id' => 2, 'name' => 'Item B'],
    ],
];

$toon = $serializer->serialize($data, 'toon', [
    'toon_options' => ['delimiter' => '|'],
]);
```

Output:

```
products[2|]{id|name}:
  1|Item A
  2|Item B

```

Symfony Integration
-------------------

[](#symfony-integration)

### Manual Service Registration

[](#manual-service-registration)

In `config/services.yaml`:

```
services:
  MountSoftware\SymfonyToonSerializer\Encoder\ToonEncoder:
    arguments:
      $defaultOptions:
        delimiter: ','
        strict: true
    tags:
      - { name: serializer.encoder }

  MountSoftware\SymfonyToonSerializer\ToonService:
    arguments:
      $defaultOptions:
        delimiter: ','
```

### Auto-configuration

[](#auto-configuration)

If using Symfony auto-configuration, the encoder will be automatically registered if tagged properly. The library is designed to work with Symfony's standard service discovery.

Testing
-------

[](#testing)

Run the test suite:

```
composer test
```

Or with PHPUnit directly:

```
vendor/bin/phpunit
```

The test suite includes 76 tests covering:

- ✅ Simple object encoding/decoding
- ✅ Nested object handling
- ✅ Primitive array inline notation
- ✅ Tabular array formats
- ✅ Mixed and heterogeneous arrays
- ✅ Delimiter variants (comma, tab, pipe)
- ✅ Quoting and special character handling
- ✅ Error handling and strict mode validation
- ✅ Empty objects and arrays
- ✅ Round-trip data integrity
- ✅ Option validation (delimiters, indent, strict mode)
- ✅ Context option extraction (namespaced)
- ✅ Invalid option error handling

TOON Format
-----------

[](#toon-format)

TOON (Token-Oriented Object Notation) is a data serialization format designed for efficiency and readability. Key features:

- **Compact**: Optimized for minimal token usage in LLM contexts
- **Human-readable**: Easy to read and write by hand
- **Structured**: Supports objects, arrays, and primitives
- **Tabular**: Efficient representation of uniform data
- **Flexible delimiters**: Choose between comma, tab, or pipe

For more details on the TOON format, see the [helgesverre/toon documentation](https://github.com/HelgeSverre/toon).

Known Limitations
-----------------

[](#known-limitations)

The underlying TOON library has some limitations for round-trip encoding/decoding:

1. **Mixed arrays with nested objects**: When encoding mixed arrays where list items contain objects (e.g., `[1, ['a' => 1], 'text']`), the nested object is decoded as a string rather than an associative array. This is due to how the TOON format represents inline objects in list contexts.
2. **Arrays of arrays as list items**: Similar to above, inline array notation in list items may not round-trip perfectly.

For best round-trip support, use:

- Tabular format for uniform arrays of objects
- Inline notation for simple primitive arrays
- Nested indentation for complex nested structures

Contributing
------------

[](#contributing)

Contributions are welcome! Please ensure:

1. All tests pass: `composer test`
2. Code follows PSR-12 standards
3. New features include tests
4. Documentation is updated

License
-------

[](#license)

MIT License. See [LICENSE](LICENSE) file for details.

Credits
-------

[](#credits)

- Built by [Mount Software](https://mountsoftware.com)
- Uses [helgesverre/toon](https://github.com/HelgeSverre/toon) for TOON encoding/decoding
- Integrates with [Symfony Serializer](https://symfony.com/doc/current/components/serializer.html)

Links
-----

[](#links)

- [TOON Format Specification](https://github.com/HelgeSverre/toon)
- [Symfony Serializer Documentation](https://symfony.com/doc/current/components/serializer.html)
- [Issue Tracker](https://github.com/mountsoftware/symfony-toon-serializer/issues)

###  Health Score

38

—

LowBetter than 86% of packages

Maintenance77

Regular maintenance activity

Popularity15

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity44

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 75% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

123d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/d1c85378c7451415dd52a96a67aaec56633c49146bded33ac603b721e00a4846?d=identicon)[mincua](/maintainers/mincua)

---

Top Contributors

[![claude](https://avatars.githubusercontent.com/u/81847?v=4)](https://github.com/claude "claude (6 commits)")[![mincua](https://avatars.githubusercontent.com/u/594930?v=4)](https://github.com/mincua "mincua (2 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/mountsoftware-symfony-toon-serializer/health.svg)

```
[![Health](https://phpackages.com/badges/mountsoftware-symfony-toon-serializer/health.svg)](https://phpackages.com/packages/mountsoftware-symfony-toon-serializer)
```

###  Alternatives

[api-platform/core

Build a fully-featured hypermedia or GraphQL API in minutes!

2.6k47.0M207](/packages/api-platform-core)[friendsofsymfony/jsrouting-bundle

A pretty nice way to expose your Symfony routing to client applications.

1.5k52.7M206](/packages/friendsofsymfony-jsrouting-bundle)[sonata-project/admin-bundle

The missing Symfony Admin Generator

2.1k18.7M279](/packages/sonata-project-admin-bundle)[symfony/serializer-pack

A pack for the Symfony serializer

1.1k27.9M199](/packages/symfony-serializer-pack)[icanhazstring/composer-unused

Show unused packages by scanning your code

1.7k6.8M153](/packages/icanhazstring-composer-unused)[spatie/phpunit-snapshot-assertions

Snapshot testing with PHPUnit

69417.3M441](/packages/spatie-phpunit-snapshot-assertions)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
