Serializer
SerializerProvider
Class : Claroline\AppBundle\API\SerializerProvider
The SerializerProvider
is in charge of the serialization/deserialization process of the application Entities.
Usages
The provider is a standard service registered in the Symfony ServiceContainer.
It can be retrieved from the container
or directly injected inside another service.
1
2
3
4
services:
MyCustomService:
arguments:
- '@Claroline\AppBundle\API\SerializerProvider'
You can now use it in your own service :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// ...
use Claroline\AppBundle\API\SerializerProvider;
class MyCustomService
{
private SerializerProvider $serializer;
public function __construct(SerializerProvider $serializer)
{
$this->serializer = $serializer;
}
public function myCustomMethod()
{
$serialized = $this->serializer->serialize($myCustomObject);
}
}
Methods
Once you’ve injected or retrieved the provider, you have access to the following methods :
serialize(mixed $object, array $options = [])
Converts an Entity into a serializable (we use associative arrays) structure.
Arguments
$object
(mixed) : the entity to serialize. The provider will retrieve the correct serializer instance by inspecting the class of$object
.$options
(array) : a list of options for serialization.
Returns
(array) A serializable array representation of $object
.
Example
1
2
3
4
5
6
7
8
9
10
11
12
use Claroline\CoreBundle\Entity\User;
use Claroline\AppBundle\API\Options;
// ...
$user = new User();
// gets the default serialized version of the user
$serializedUser = $this->serializerProvider->serialize($user);
// adds an option to get the minimal version of the user
$serializedUser = $this->serializerProvider->serialize($user, [Options::SERIALIZE_MINIMAL]);
deserialize(string $class, array $data, array $options = [])
Converts a serializable structure into the Entity $class
.
Arguments
$class
(string) : the full class name (including namespace) of the target entity.$data
(mixed) : the serialized data to use to populate the object.$options
(array) : a list of options for deserialization.
Returns
(mixed) An instance of $class
filled with the content of $data
.
Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
use Claroline\CoreBundle\Entity\User;
// ...
$serializedUser = [
'firstName' => 'John',
'lastName' => 'Doe'
'email' => 'john.doe@claroline.com'
];
// get a User entity from the serialized data
$user = $this->serializerProvider->deserialize(User::class, $serializedUser);
echo $user instanceof User; // true
echo $user->getFirstName(); // John
Serializer instances
Namespace : MyVendor\MyBundle\Serializer\MySerializer
Dependency Injection Tag : claroline.serializer
The Serializer
is a service in charge of the serialization/deserialization of an Entity (and it’s associations).
Note
All entities in the application don’t require their own serializer. In most cases, there is only one
Serializer
for each object exposed in the JSON API (which includes a main Entity and it’s associations).Some complex cases (like quiz resource) use multiple serializers for development purposes. In these cases, the additional serializers SHOULD NOT be registered in the
SerializerProvider
.
Register into the SerializerProvider
In order to be able to access a Serializer
from the SerializerProvider
, you need to register it.
For this, we use the symfony Tagged Services.
1
2
3
4
5
6
# MY_PLUGIN/Resources/config/services/serializer.yml
services:
MySerializer:
tags: [claroline.serializer]
Methods
Here is the list of the standard serializer methods.
getClass()
Gets the full class name of the object managed by the serializer instance.
Note
If none is provided we will use the type hint of the
$object
argument ofserialize()
method.
Arguments
none
Returns
(string) The full class of the managed object.
Example
1
2
3
4
5
6
7
8
9
use MyVendor\MyBundle\Entity\MyObject;
class MySerializer
{
public function getClass()
{
return MyObject::class;
}
}
serialize(mixed $object, array $options = [])
Arguments
$object
(mixed) : the object to serialize.$options
(array) : a list of options for serialization.
Returns
(array) A serializable array representation of $object
.
Example
1
2
3
4
5
6
7
8
9
10
11
12
use MyVendor\MyBundle\Entity\MyObject;
class MySerializer
{
public function serialize(MyObject $object, array $options = [])
{
return [
'name' => $object->getName(),
// other serialized properties
];
}
}
deserialize(array $data, mixed $object = null, array $options = [])
Arguments
$data
(array) : the serialized data to use to populate the object.$object
(mixed) : the entity instance to populate.$options
(array) : a list of options for deserialization.
Returns
(mixed) The updated $object
with $data
props.
Example
1
2
3
4
5
6
7
8
9
10
11
use MyVendor\MyBundle\Entity\MyObject;
class MySerializer
{
public function deserialize(array $data, MyObject $object, array $options = [])
{
$object->setName($data['name']);
// here goes the full deserialization process of the object
}
}
Options
You can alter the Serializer
behavior by passing an array of options to the serialize()
and deserialize()
SerializerTrait
Class : Claroline\AppBundle\API\Serializer\SerializerTrait
You can use the SerializerTrait
to have access to some serialization utilities.
Methods
sipe(string $prop, string $setter, array $data, mixed $object)
An utility method (alias of setIfPropertyExist
) to easily populate an object $object
with
an array of data $data
.
It uses string selectors like lodash ones to retrieve data inside
the input array. Each .
in the string will go one level deeper in the array. For example meta.description
will returns $data['meta']['description']
.
If meta
doesn’t exist it will return null
without error.
This permits to avoid additional isset()
checks in deserialize()
implementations.
Arguments
$prop
(string) : the path to the prop inside the$data
array.$setter
(string) : the name of the setter to use (it MUST be a public method of$object
).$data
(array) : the serialized data to use to populate the object.$object
(mixed) : the object instance to populate.
Returns
void
Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
use Claroline\AppBundle\API\Serializer\SerializerTrait;
use Claroline\CoreBundle\Entity\User;
class MySerializer
{
// use the trait in your serializer
use SerializerTrait;
public function deserialize(array $data, User $user = null)
{
// set the name of the entity
$this->sipe('name', 'setName', $data, $object)
// you can use lodash like selectors to deep select in $data
$this->sipe('meta.description', 'setDescription', $data, $object)
}
}
Full Serializer
example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
use Claroline\AppBundle\API\Serializer\SerializerTrait;
use JMS\DiExtraBundle\Annotation as DI;
use MyVendor\MyBundle\Entity\MyObject;
/**
* @DI\Service("my_plugin.serializer.my_object")
* @DI\Tag("claroline.api.serializer")
*/
class MySerializer
{
use SerializerTrait;
public function getClass()
{
return 'MyVendor\MyBundle\Entity\MyObject';
}
public function getResources()
{
return '#/plugin/my/my-object';
}
public function serialize(MyObject $object, array $options = [])
{
$serialized = [];
// TODO : implement
return $serialized;
}
public function deserialize(array $data, MyObject $object = null, array $options = [])
{
// TODO : implement
return $object;
}
}
Best practices
You SHOULD avoid extra DB fetch.
The Serializer
are also used by Finder
, adding DB queries will slightly decreases
performances. If you need to add extra data, you should add on Options
to toggle it.
YOU MUST NOT persist()
or flush()
the ObjectManager.
Serialization is not only about persistence. We sometimes serialize/deserialize data for easier manipulations and we don’t want the underlying entities to be modified.