Deserialize data into a PHP object using Symfony Serializer
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.
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:
- The data (as a string) to be decoded (e.g., XML, JSON, etc).
- The name of the class to decoded the data to.
- 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
Thanks for your comment 🙏. Once it's approved, it will appear here.
Leave a comment