liamhackett / valueobjectcompiler
Compile strict type, read only value objects from JSON and XML
Requires
- php: ^8.2||^8.3||^8.4||^8.5
- ext-simplexml: *
- symfony/console: *
- symfony/process: *
Requires (Dev)
- ext-libxml: *
- doctrine/coding-standard: ^14.0
- php-coveralls/php-coveralls: ^2.7.0
- phpstan/phpstan: ^2.2.13
- phpunit/phpunit: ^13.3.3
- roave/security-advisories: dev-latest
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-09-11 12:09:54 UTC
README
This package takes a source file, such as JSON or XML and creates strict typed, PSR12, readonly Value Objects.
The aim is to slowly support more file formats with the same file output.
Installation
composer require --dev liamhackett/valueobjectcompiler
How To Use
Single file Compiler
vendor/bin/ValueObjectCompiler compile:json {jsonLocation} --outputDir={dir}
vendor/bin/ValueObjectCompiler compile:xml {xmlLocation} --outputDir={dir}
Single file compiler will take a JSON or XML file and output its value object representation. By default, it will output in the current Directory, but you can specify your own directory using the outputDir flag.
JSON Example
example.json
{
"id": 12,
"name": "Json Object",
"status": "Published",
"tags": ["tag1", "tag2", "tag3"],
"sub_objects": [
{
"name": "Hello",
"value": 13.132
},
{
"name": "World",
"value": null
}
]
}
Example.php
<?php readonly class Example { /** * @var string[] $tags * @var SubObject[] $subObjects */ public function __construct( public int $id, public string $name, public string $status, public array $subObjects, public array $tags, ) { } /** * @return self[] */ public static function hydrateMany(array $bulkData): array { $result = []; foreach ($bulkData as $data) { $result[] = self::hydrate($data); } return $result; } public static function hydrate(array $data): self { if (!isset($data['id'], $data['name'], $data['status'], $data['sub_objects'], $data['tags'])) { throw new \RuntimeException('Missing required parameter'); } return new self( id: $data['id'], name: $data['name'], status: $data['status'], subObjects: SubObject::hydrateMany($data['sub_objects']), tags: $data['tags'], ); } }
SubObject.php
<?php readonly class SubObject { public function __construct( public string $name, public ?float $value = null, ) { } /** * @return self[] */ public static function hydrateMany(array $bulkData): array { $result = []; foreach ($bulkData as $data) { $result[] = self::hydrate($data); } return $result; } public static function hydrate(array $data): self { if (!isset($data['name'])) { throw new \RuntimeException('Missing required parameter'); } return new self( name: $data['name'], value: $data['value'] ?? null, ); } }
XML Example
example.xml
<?xml version="1.0" encoding="UTF-8"?> <catalog> <book id="bk101"> <author>Example Author</author> <title>Sample Title</title> <genre>Fiction</genre> <price>19.99</price> <publish_date>2023-01-01</publish_date> <description>A brief description of the book.</description> </book> <book id="bk102"> <author>Example Author 2</author> <title>Another Sample Title</title> <genre>Fiction</genre> <price>25.99</price> <publish_date>2025-01-01</publish_date> <description>A brief description of the book.</description> </book> </catalog>
Catalog.php
<?php readonly class Catalog { /** * @param Book[] $book */ public function __construct( public array $book, ) { } /** * @return self[] */ public static function hydrateMany(array $bulkData): array { $result = []; foreach ($bulkData as $data) { $result[] = self::hydrate($data); } return $result; } public static function hydrate(\SimpleXMLElement $data): self { if ((string)$data->book === '') { throw new \RuntimeException('Missing required parameter'); } return new self(book: Book::hydrateMany(iterator_to_array($data->book, false)),); } }
Book.php
<?php readonly class Book { public function __construct( public string $author, public string $description, public string $genre, public string $id, public float $price, public string $publishDate, public string $title, ) { } /** * @return self[] */ public static function hydrateMany(array $bulkData): array { $result = []; foreach ($bulkData as $data) { $result[] = self::hydrate($data); } return $result; } public static function hydrate(\SimpleXMLElement $data): self { if ( !isset($data['id']) || (string)$data->author === '' || (string)$data->description === '' || (string)$data->genre === '' || (string)$data->price === '' || (string)$data->publish_date === '' || (string)$data->title === '' ) { throw new \RuntimeException('Missing required parameter'); } return new self( author: $data->author->__toString(), description: $data->description->__toString(), genre: $data->genre->__toString(), id: $data['id'], price: (float) $data->price->__toString(), publishDate: $data->publish_date->__toString(), title: $data->title->__toString(), ); } }