sajad torkamani

What is deserialization?

Deserialization is the process of converting a data string in a format like JSON or XML into a PHP object. It involves first decoding the data string into a PHP array and then denormalizing the array into a PHP object. Deserialization is the opposite of serialization.

Deserialization plays an essential part in building web services / REST APIs because you must be able to convert application-specific data types (e.g., a Customer or PolicyQuote PHP object) into a format (usually JSON) that can be easily consumed by clients or other web services.

Deserialize data into a PHP object using Symfony Serializer

How to deserialize

Install dependencies

Install the Serializer component:

composer require symfony/serializer

Assuming you’ll use the ObjectNormalizer as your normalizer, install the PropertyAccess component that it depends on:

composer require symfony/property-access

Use serializer

Instantiate a serializer that implements the SerializerInterface and call its deserialize method which takes three arguments:

  1. The data (as a string) to be decoded (e.g., XML, JSON, etc).
  2. The name of the class to decoded the data to.
  3. The encoder to use to convert the data into a PHP array.
<?php

// src/deserialize.php

use App\Entity\Person;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Encoder\XmlEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;

require 'vendor/autoload.php';

$encoders = [new XmlEncoder(), new JsonEncoder()];
$normalizers = [new ObjectNormalizer()];
$serializer = new Serializer($normalizers, $encoders);

$data = <<<EOF
<person>
    <name>Sajad</name>
    <age>28</age>
    <isAlive>true</isAlive>
</person>
EOF;

$person = $serializer->deserialize($data, Person::class, 'xml');

dump($person);

Running this should output:

App\Entity\Person {#18php 
  -age: "28"
  -name: "Sajad"
  -isAlive: true
}

Handle additional attributes that don’t have a 1-1 mapping

By default, additional attributes that don’t map to the denormalized object will be ignored by the Serializer component. So, if in the example above, we had a <gender>Male</gender> XML attribute but there was no corresponding $gender property in the Person class, the Serializer component would silently ignore <gender>.

You can instead choose to throw an exception when an unrecognized attribute is given:

use App\Model\Person;

$data = <<<EOF
<person>
    <name>Sajad</name>
    <age>28</age>
    <isAlive>true</isAlive>
    <gender>Male</gender>
</person>
EOF;

$classMetadataFactory = new ClassMetadataFactory($loader);
$normalizer = new ObjectNormalizer($classMetadataFactory);
$serializer = new Serializer([$normalizer]);

// this will throw a Symfony\Component\Serializer\Exception\ExtraAttributesException
// because "city" is not an attribute of the Person class
$person = $serializer->deserialize($data, Person::class, 'xml', [
    AbstractNormalizer::ALLOW_EXTRA_ATTRIBUTES => false,
]);

Deserialize into an existing object

You can also deserialize data into an existing object:

// ...
$person = new Person();
$person->setName('bar');
$person->setAge(99);
$person->setSportsperson(true);

$data = <<<EOF
<person>
    <name>foo</name>
    <age>69</age>
</person>
EOF;

$serializer->deserialize($data, Person::class, 'xml', [AbstractNormalizer::OBJECT_TO_POPULATE => $person]);
// $person = App\Model\Person(name: 'foo', age: '69', sportsperson: true)

This is a common use case when working with Doctrine ORM. For example, if a client makes a PATCH request to update an existing resource, you’ll typically load an entity first and deserialize the incoming data into the entity.

Sources

References (3)

Posts that link to this one.

Mentions (2)

Posts this one links to.