thiagocordeiro / serializer
Requires
- php: >=8.2
- ext-json: *
Requires (Dev)
- phpstan/phpstan: ^1.4
- phpunit/phpunit: ^9.5
- slevomat/coding-standard: ^7.0
- symfony/var-dumper: ^6.0
README
This package allows you to parse json objects into php classes without the overhead of annotations, it checks for php object constructor and creates cache classes to convert json into a given class.
How to use
For Symfony projects a bundle is available at serializer-bundle
For Laravel projects a package is available at laravel-serializer
otherwise the package is available on composer:
composer require thiagocordeiro/serializer
PHP Serializer does not use setters, so your class must have a constructor with all properties coming from the json.
Basic example (Using getters)
<?php declare(strict_types=1); namespace App\ValueObject; class User { private string $name; private string $email; public function __construct(string $name, string $email) { $this->name = $name; $this->email = $email; } public function getName(): string { return $this->name; } public function getEmail(): string { return $this->email; } }
Basic example (Using readonly properties)
class User { public readonly string $name; public readonly string $email; public function __construct(string $name, string $email) { $this->name = $name; $this->email = $email; } }
Once you have your class, you can convert json string to it, ex.
use Serializer\Builder\Encoder\EncoderFactory; use Serializer\Builder\Encoder\FileLoader\PipelineEncoderFileLoader; use Serializer\Builder\Decoder\DecoderFactory; use Serializer\Builder\Decoder\FileLoader\PipelineDecoderFileLoader; use Serializer\JsonSerializer; $encoder = new EncoderFactory(PipelineEncoderFileLoader::full('path/to/cache')); $decoder = new DecoderFactory(PipelineDecoderFileLoader::full('path/to/cache')); $serializer = new JsonSerializer($encoder, $decoder); $json = '{"name":"Arthur Dent","email":"arthur.dent@galaxy.org"}'; $serializer->deserialize($json, \App\ValueObject\User::class); // or $json = '[ {"name":"Arthur Dent","email":"arthur.dent@galaxy.org"}, {"name":"Chuck Norris","email":"chuck@norrs.com"}, ... ]'; $serializer->deserialize($json, \App\ValueObject\User::class);
The opposite way, ex.
use Serializer\Builder\Encoder\EncoderFactory; use Serializer\Builder\Encoder\FileLoader\PipelineEncoderFileLoader; use Serializer\Builder\Decoder\DecoderFactory; use Serializer\Builder\Decoder\FileLoader\PipelineDecoderFileLoader; use Serializer\JsonSerializer; $encoder = new EncoderFactory(PipelineEncoderFileLoader::full('path/to/cache')); $decoder = new DecoderFactory(PipelineDecoderFileLoader::full('path/to/cache')); $serializer = new JsonSerializer($encoder, $decoder); $user = new \App\ValueObject\User('Arthur Dent', 'arthur.dent@galaxy.org'); $json = $serializer->serialize($user); // will return {"name":"Arthur Dent","email":"arthur.dent@galaxy.org"} // or $json = $serializer->serialize([$user1, $user2, ...]);
Complex object construction - Objects
Constructors can also have arrays and other classes on it , the other class must follow same rules, for ex.
<?php declare(strict_types=1); namespace App\ValueObject; class User { // properties... public function __construct(string $name, string $email, ?Address $address) { $this->name = $name; $this->email = $email; $this->address = $address; } // getters }
for this example a json string could contain or not address
property:
{ "name": "Arthur Dent", "email": "arthur.dent@galaxy.org" }
or
{ "name": "Arthur Dent", "email": "arthur.dent@galaxy.org", "address": { "street": "Times Square", "contry": "USA" } }
Complex object construction - Arrays
Arrays are also welcome, but since there is no way to determine on the array type on object constructor, arrays require you to write php annotation, a simple doc bloc is everything it needs to deserialize any json string, ex
<?php use ValueObject\Address; class User { // properties... /** * @param Address[] $addresses */ public function __construct(string $name, array $addresses) { $this->name = $name; $this->addresses = $addresses; } // getters }
A json for this class would be:
{ "name": "Arthur Dent", "addresses": [ {"street":"Times Square", "contry": "USA"}, {"street":"Leidseplein", "contry": "Netherlands"} ] }
Default values
By default all non-provided values will be filled with null
, if the property is not nullable then you a TypeError
will be thrown, but a property can also have a default value and in case it is not given, the default value will be used, ex.
<?php declare(strict_types=1); namespace App\ValueObject; class User { // properties... public function __construct(string $name, string $email, string $type = 'user') { $this->name = $name; $this->email = $email; $this->type = $type; } // getters }
A json without type
would result an object with $type = 'user'
.
Note: Default value will only be used in case it is not provided, if it is provided as null
then null
will be the value.
Constructor with arguments
<?php declare(strict_types=1); namespace App\ValueObject; class User { // properties... public function __construct(Place ...$places) { $this->places = $places; } // getters }
Constructor with DateTime/DateTimeImmutable
<?php declare(strict_types=1); namespace App\ValueObject; class User { // properties... public function __construct(DateTime $createdAt, DateTimeImmutable $updatedAt) { $this->createdAt = $createdAt; $this->updatedAt = $updatedAt; } // getters }
Contributing
Feel free to open issues or submit PRs
Supporting
If you feel like supporting changes then you can send donations to the address below.
Bitcoin Address: bc1qfyudlcxqnvqzxxgpvsfmadwudg4znk2z3asj9h