haskel / map-serializer
Object Serializer by map
Requires
- nette/php-generator: ^3.2
- symfony/yaml: ~4.0|~5.0
This package is auto-updated.
Last update: 2024-10-17 19:09:22 UTC
README
Use different tiny and simple schemas to serialize your objects and other structs
Installation
composer require haskel/map-serializer
Example
/** Define a class that you want to serialize */ class User { private $id; private $name; private status = 0; private $role; private $phone; private $mail; private group; public function __construct($id, $name, $role) { $this->id = $id; $this->name = $name; $this->role = $role; } /** * ... Boring code with getters and setters ... */ } /** Specify the schema */ $schema = [ 'id' => 'int', 'name' => 'string', 'status' => 'int', 'role' => 'string', ]; /** Add this schema definition, uniq schema name and class name to serializer */ $serializer->addSchema(User::class, 'default', $schema); /** serialize some instance of the class */ $result = $serializer->serialize(new User('Alice', 'user'));
{ id: 1, name: 'Alice', status: 0, role: 'user' }
Usage
Basic usage
Register different schemas for specific class.
Use second argument of serialize()
method to specify a schema.
use Haskel\MapSerializer\Serializer; $serializer = new Serializer(); $schemas = [ 'default' => [ 'id' => 'int', 'name' => 'string', 'status' => 'int', 'role' => 'string', ], 'short' => [ 'id' => 'int', 'name' => 'string', ] ]; foreach ($orderSchemas as $schemaName => $schema) { $serializer->addSchema(User::class, $schemaName, $schema); } $users = [ new User(1, 'Alice'), new User(2, 'Bob'), ]; $result = $serializer->serialize($users, 'short');
[ { id: 1, name: 'Alice' }, { id: 2, name: 'Bob' } ]
Nested objects
- add schema with name
- use this name to nest an object
use Haskel\MapSerializer\Serializer; $serializer = new Serializer(); $userSchema = [ 'id' => 'int', 'name' => 'string', 'group' => 'short', ]; $groupSchema = [ 'id' => 'int', 'name' => 'string', ]; $serializer->addSchema(User::class, 'default', $userSchema); $serializer->addSchema(Group::class, 'short', $groupSchema); $group = new Group('sales'); $user = new User('Alice'); $user->addToGroup($group); $result = $serializer->serialize($user);
{ id: 1, name: 'Alice', group: { id: 1, name: 'sales' } }
Format you object as you really want
Formatter is an object which define specific transformation rules for entity.
Formatter should implement Haskel\MapSerializer\Formatter
interface
Look at this example
interface Formatter { public function format($value, $schemaName); } class DatetimeFormatter implements Formatter { public function format($value, $schemaName) { if (!$value instanceof DateTime) { throw new FormatterException(sprintf('wrong value type')); } switch ($schemaName) { case 'default': case 'datetime': default: return $value->format("Y-m-d H:i:s"); case 'date': return $value->format('Y-m-d'); case 'time': return $value->format('H:i:s'); } } }
How it works
use Haskel\MapSerializer\Formatter\DatetimeFormatter; use Haskel\MapSerializer\Serializer; $serializer = new Serializer(); $serializer->addFormatter(new DatetimeFormatter()); $datetime = new DateTime('2015-10-21 12:00:00'); $serializer->format($datetime, 'date');
'2015-10-21'
How to accelerate extracting
Extractors are autogenerated classes that help you to extract fields from an object of some class.
ExtractorGenerator
generates classes those can extract fields fastly without using reflection and without analysing of class structure.
It looks like that:
final class AppEntityUserExtractor extends \Haskel\MapSerializer\EntityExtractor\BaseExtractor { /** @var \App\Entity\User */ protected $entity; protected function extract() { return [ "id" => $this->entity->getId(), "name" => $this->entity->getName(), ]; } public function exists($fieldName) { if (count($this->fields) === 0) { $this->fields = $this->extract(); } return array_key_exists($fieldName, $this->fields); } /** * @param $fieldName * * @return mixed */ public function get($fieldName) { if (count($this->fields) === 0) { $this->fields = $this->extract(); } return $this->fields[$fieldName]; } }
Extracting works automatically, but if you want to specify your own extractor it would be easy.
Just implement an interface \Haskel\MapSerializer\EntityExtractor\Extractor
.
namespace Haskel\MapSerializer\EntityExtractor; interface Extractor { public function get($fieldName); public function exists($fieldName); } class UserExtractor implements Extractor { public function get($fieldName) { return 42; } public function exists($fieldName) { return true; } }
And register it in your serializer for specific scheme
$schema = [ 'id' => 'int', 'name' => 'string', 'status' => 'int', 'role' => 'string', ]; $serializer->addSchema(User::class, 'default', $schema); $serializer->addExtractor(User::class, 'default', UserExtractor::class); $result = $serializer->serialize(new User('Alice'));
{ id: 42, name: '42', status: 42, role: '42' }