kariricode / serializer
Multi-format serialization engine for PHP 8.4+ — JSON, XML, CSV, QueryString, #[Serialize] attributes, powered by kariricode/property-inspector. ARFA 1.3.
Package info
github.com/KaririCode-Framework/kariricode-serializer
pkg:composer/kariricode/serializer
Requires
- php: ^8.4
- kariricode/property-inspector: ^2.0
This package is auto-updated.
Last update: 2026-03-06 13:32:51 UTC
README
Multi-format serialization for PHP 8.4+ — JSON, XML, CSV, QueryString, zero dependencies.
Installation · Quick Start · Attribute-Driven · All Encoders · Architecture
The Problem
Multi-format serialization for PHP always pulls in heavy dependencies or loses the data contract:
// symfony/serializer: 7+ packages, complex config, annotation magic // league/fractal: transformer boilerplate, no attribute support // json_encode/decode alone: no groups, no field renaming, no XML/CSV // Switching from JSON to XML means rewriting your serialization layer entirely.
The Solution
use KaririCode\Serializer\Provider\SerializerServiceProvider; $engine = (new SerializerServiceProvider())->createEngine(); // One API, four formats — swap format string to change output $json = $engine->serialize(['name' => 'Walmir', 'age' => 30], 'json'); $xml = $engine->serialize(['name' => 'Walmir', 'age' => 30], 'xml', ['root' => 'user']); $csv = $engine->serialize([['name' => 'Walmir', 'age' => 30]], 'csv'); $qs = $engine->serialize(['name' => 'Walmir', 'age' => 30], 'query_string'); // RFC 8259 (JSON) · RFC 4180 (CSV) · RFC 3986 (URL) — built-in compliance
Requirements
| Requirement | Version |
|---|---|
| PHP | 8.4 or higher |
| ext-simplexml | Built-in (required for XML) |
| kariricode/property-inspector | ^2.0 |
Installation
composer require kariricode/serializer
Quick Start
<?php require_once __DIR__ . '/vendor/autoload.php'; use KaririCode\Serializer\Provider\SerializerServiceProvider; $engine = (new SerializerServiceProvider())->createEngine(); // Serialize array to JSON $result = $engine->serialize(['name' => 'Walmir', 'age' => 30], 'json'); echo $result->getPayload(); // '{"name":"Walmir","age":30}' // Deserialize JSON to array $data = $engine->deserialize('{"name":"Walmir"}', 'json'); // ['name' => 'Walmir'] // XML with custom root tag $result = $engine->serialize(['name' => 'Walmir'], 'xml', ['root' => 'user']); // <user><name>Walmir</name></user>
Attribute-Driven DTO Serialization
use KaririCode\Serializer\Attribute\Serialize; class UserDto { #[Serialize(name: 'user_id', groups: ['admin'])] public int $id = 42; #[Serialize(groups: ['public', 'admin'])] public string $name = 'Walmir Silva'; #[Serialize(ignore: true)] public string $passwordHash = '...'; } $provider = new SerializerServiceProvider(); $serializer = $provider->createAttributeSerializer(); // Serialize to JSON (public group) $json = $serializer->serialize(new UserDto(), 'json', ['public']); // {"name":"Walmir Silva"} // Serialize to JSON (admin group) $json = $serializer->serialize(new UserDto(), 'json', ['admin']); // {"user_id":42,"name":"Walmir Silva"} // Deserialize from JSON $dto = $serializer->deserialize('{"name":"Walmir"}', UserDto::class, 'json');
All 4 Encoders
| Format | Encoder | MIME Type | PHP Functions |
|---|---|---|---|
json |
JsonEncoder | application/json | json_encode/decode with JSON_THROW_ON_ERROR |
xml |
XmlEncoder | application/xml | SimpleXMLElement + DOMDocument |
csv |
CsvEncoder | text/csv | fputcsv/str_getcsv via php://temp |
query_string |
QueryStringEncoder | application/x-www-form-urlencoded | http_build_query/parse_str |
Adding Custom Encoders
use KaririCode\Serializer\Contract\Encoder; final readonly class YamlEncoder implements Encoder { public function encode(array $data, SerializationContext $context): string { /* ... */ } public function decode(string $payload, SerializationContext $context): array { /* ... */ } public function supports(string $format): bool { return $format === 'yaml'; } public function getFormat(): string { return 'yaml'; } } $registry = $provider->createRegistry(); $registry->register(new YamlEncoder());
Engine API (Programmatic)
$engine = (new SerializerServiceProvider())->createEngine(); $result = $engine->serialize(['name' => 'Walmir', 'age' => 30], 'json'); $result->getPayload(); // '{"name":"Walmir","age":30}' $result->getFormat(); // 'json' $result->getPayloadSize(); // byte count $data = $engine->deserialize('{"name":"Walmir"}', 'json'); // ['name' => 'Walmir'] // CSV with custom separator $result = $engine->serialize([['a' => 1, 'b' => 2]], 'csv', ['separator' => ';']);
Ecosystem Position
DPO Pipeline: Input → Validator → Sanitizer → Transformer → Business Logic
Infra Pipeline: Object ↔ Normalizer ↔ Array ↔ ★ Serializer ★ ↔ String
Cross-Layer: Request DTO ↔ Mapper ↔ Domain Entity ↔ Mapper ↔ Response DTO
The Serializer converts already-normalized arrays into wire-format strings for transport. It is the last step in the infrastructure pipeline before the payload leaves the application.
Architecture
Source layout
src/
├── Attribute/ Serialize — name, groups, ignore annotation
├── Configuration/ SerializerConfiguration (immutable)
├── Contract/ Encoder · SerializationContext · SerializerEngine · EncoderRegistry
├── Core/ SerializerEngine · SerializationContextImpl · InMemoryEncoderRegistry
├── Encoder/ JsonEncoder · XmlEncoder · CsvEncoder · QueryStringEncoder
├── Exception/ SerializationException
└── Provider/ SerializerServiceProvider — factory for engine & attribute serializer
Key design decisions
| Decision | Rationale | ADR |
|---|---|---|
| Format-agnostic engine | Swap format string — no code changes | ADR-001 |
| Serialization groups | Field visibility per consumer without multiple DTOs | ADR-002 |
| RFC compliance | JSON 8259, CSV 4180, URL 3986 | ADR-003 |
| Property Inspector integration | Attribute scanning delegated to kariricode/property-inspector | ADR-004 |
| Zero encoder dependencies | All 4 encoders use only PHP built-ins | ADR-005 |
Specifications
| Spec | Covers |
|---|---|
| SPEC-001 | Encoder interface and registration |
| SPEC-002 | #[Serialize] groups and field mapping |
| SPEC-003 | SerializeAttributeHandler contract and invariants |
Project Stats
| Metric | Value |
|---|---|
| PHP source files | 20 |
| Source lines | ~810 |
| Test files | 13 |
| Test lines | ~700 |
| External runtime dependencies | 1 (kariricode/property-inspector) |
| Encoder classes | 4 |
| Supported formats | JSON, XML, CSV, QueryString |
| PHPStan level | 9 |
| PHP version | 8.4+ |
| ARFA compliance | 1.3 |
Contributing
git clone https://github.com/KaririCode-Framework/kariricode-serializer.git cd kariricode-serializer composer install kcode init kcode quality # Must pass before opening a PR
License
Part of the KaririCode Framework ecosystem.
kariricode.org · GitHub · Packagist · Issues