Serialization

In PHP world
by m1r1k
Serialization?
Serialization is the process of translating data structures or object state into a format that can be stored (for example, in a file or memory buffer, or transmitted across a network connection link) and reconstructed later in the same or another computer environment.

What could be easier?

$obj = (object) [
'id' => 15,
'label' => 'Serialize me!',
'tags' => [
'Tag1', 'Tag2', 'Tag3'
],
];
// Let's represent it as a string.serialize()/deserialize()

echo serialize($obj);
// 'O:8:"stdClass":3:{
// s:2:"id";i:15;
// s:5:"label";s:13:"Serialize me!";
// s:4:"tags";a:2:{
// i:0;s:4:"Tag1";
// i:1;s:4:"Tag2";
// }
// }'
json_encode()/json_decode()

echo json_encode($obj);
// {
// "id": 15,
// "label": "Serialize me!",
// "tags": [
// "Tag1",
// "Tag2"
// ]
// }
SimpleXML

$xml = simplexml_load_string("<?xml version='1.0'><document />");
foreach ((array) $obj as $key => $value) {
$xml->addChild($key, $value);
}
echo $xml->asXML();
// <?xml version="1.0"?>
// <object>
// <id>15</id>
// <label>Serialize me!</label>
// <empty/>
// </object>
But we have other formats

- YAML
- HAL
- Xliff
- Custom formated XML
- ect
But usually we have a bit more complex data structures

Have you seen externals of ContentEntity instance?




echo strlen(serialize(node_load(1)));
// 9846
echo json_encode(node_load(1));
// {"in_preview":null}
echo \Drupal::service('serializer')->serialize(node_load(1), 'json');
// { "nid": [ { "value": "1" } ], "uuid": [ { "value": "3bc88030-1ebb-457b-9e00-db67c90efd17" } ],
// "vid": [ { "value": "1" } ], "type": [ { "target_id": "page" } ], "langcode": [ { "value": "en" } ],
// "title": [ { "value": "Abluo Capto Olim" } ], "uid": [ { "target_id": "0", "url": "\/user\/0" } ],
// "status": [ { "value": "1" } ], "created": [ { "value": "1447807663" } ], "changed": [ { "value":
// "1448367583" } ], "promote": [ { "value": "0" } ], "sticky": [ { "value": "0" } ],
// "revision_timestamp": [ { "value": "1448367583" } ], "revision_uid": [ { "target_id": "0",
// "url": "\/user\/0" } ], "revision_log": [], "revision_translation_affected": [ { "value": "1" } ],
// "default_langcode": [ { "value": "1" } ], "content_translation_source": [],
// "content_translation_outdated": [], "path": [], "body": [ { "value": "VALUE",
// "format": "plain_text", "summary": "VALUE" } ] }
What is serializer?


Serializer public API
class Serializer {
final public function serialize($data, $format, array $context = array())
final public function deserialize($data, $type, $format, array $context = array())
public function normalize($data, $format = null, array $context = array())
public function denormalize($data, $type, $format = null, array $context = array())
public function supportsNormalization($data, $format = null)
public function supportsDenormalization($data, $type, $format = null)
}
Basic usage
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Encoder\XmlEncoder;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
$encoders = array(new XmlEncoder(), new JsonEncoder());
$normalizers = array(new ObjectNormalizer());
$serializer = new Serializer($normalizers, $encoders);
$serializer->serialize($obj, 'json');
Serialization in Drupal 8
- Symfony components
- Main Serializer API
- Basic Encoders
- Serialization module
- Normalizers
- Services resolver
- Hal module
- Normalizers for HAL
- Encoder for HAL

Basic usage
$serializer = \Drupal::service('serializer');
$json_output = $serializer->serialize($node, 'json');
$deserialized_node = $serializer->deserialize($json_output,
'Drupal\Core\Entity\ContentEntityInterface', 'json', ['entity_type' => 'node']);
Drupal Normalizers
| Normalizer | Goal |
|---|---|
| ComplexDataNormalizer | Top level normalizer for all objects in drupal |
| ConfigEntityNormalizer | Normalizer to deal with config entities only |
| ContentEntityNormalizer | Normalizer to deal with content entities |
| ListNormalizer | Normalizer for iterable objects |
| TypedDataNormalizer | Normalizer for low level pieces of data |

Metadata definition
services:
serializer.normalizer.config_entity:
class: Drupal\serialization\Normalizer\ConfigEntityNormalizer
tags:
- { name: normalizer }
arguments: ['@entity.manager']
serializer.normalizer.content_entity:
class: Drupal\serialization\Normalizer\ContentEntityNormalizer
tags:
- { name: normalizer }
arguments: ['@entity.manager']
serializer.normalizer.password_field_item:
class: Drupal\serialization\Normalizer\NullNormalizer
arguments: ['Drupal\Core\Field\Plugin\Field\FieldType\PasswordItem']
tags:
- { name: normalizer, priority: 20 }
serializer.encoder.hal:
class: Drupal\hal\Encoder\JsonEncoder
tags:
- { name: encoder, priority: 10, format: hal_json }

Let's create our own format
Technical description:
- Custom formated XML
- XML comments
- Show only translatable data
http://cgit.drupalcode.org/smartling/tree/?h=8.x-1.x

Symfony and JMS Serializer
The same serializer with the same public API but...
With some adjustments :)

Flexible configuration
$serializer =
JMS\Serializer\SerializerBuilder::create()
// Set directory to store cached and compiled
// version of classes with metadata.
->setCacheDir($someWritableDir)
// Additional check if cached data is still valid.
->setDebug($trueOrFalse)
// Custom logic injection into the serialization process
->configureHandlers(function(JMS\Serializer\Handler\HandlerRegistry $registry) {
$registry->registerHandler('serialization', 'MyObject', 'json',
function($visitor, MyObject $obj, array $type) {
return $obj->getName();
}
);
})
->build();
Events
use JMS\Serializer\EventDispatcher\EventSubscriberInterface;
use JMS\Serializer\EventDispatcher\PreSerializeEvent;
class MyEventSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return array(
array('event' => 'serializer.pre_serialize', 'method' => 'onPreSerialize'),
);
}
public function onPreSerialize(PreSerializeEvent $event)
{
// do something
}
}
Events
use JMS\Serializer\EventDispatcher\EventSubscriberInterface;
use JMS\Serializer\EventDispatcher\PreSerializeEvent;
class MyEventSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return array(
array('event' => 'serializer.pre_serialize', 'method' => 'onPreSerialize'),
);
}
public function onPreSerialize(PreSerializeEvent $event)
{
// do something
}
}
And the most delicious
ANNOTATIONS!
http://jmsyst.com/libs/serializer/master/reference/annotations

Thank you
Questions?
Serialization in Symfony and Drupal 8
By Artyom Miroshnik
Serialization in Symfony and Drupal 8
- 2,154