The `symfony/serializer` component provides a powerful and flexible way to convert objects to/from various formats like JSON, XML, YAML, and more. It's an essential tool for building APIs, handling data exchange between different systems, and persisting data in diverse representations.
At its core, the component works with two main types of services:
1. Normalizers: These are responsible for transforming complex PHP data types (like objects, `DateTime` objects, collections) into simpler, scalar data types or arrays. They effectively "flatten" an object graph into a structure that can be easily understood by encoders. During denormalization, they perform the reverse operation, reconstructing objects from arrays. Key normalizers include `ObjectNormalizer` (for standard PHP objects), `DateTimeNormalizer` (for `DateTime` and `DateTimeImmutable` objects), and `ArrayDenormalizer` (for handling arrays of objects).
2. Encoders: These take the normalized data (arrays or scalar values) and convert it into a specific format string (e.g., JSON string, XML string). During denormalization, they decode a string from a specific format into a PHP array. Common encoders include `JsonEncoder`, `XmlEncoder`, and `YamlEncoder`.
The `Serializer` service orchestrates these two parts. When you serialize an object, the `Serializer` passes it through a chain of normalizers until it gets a normalized array, then passes that array to the appropriate encoder. When you denormalize a string into an object, the process is reversed: the `Serializer` uses an encoder to decode the string into an array, then passes that array through normalizers to reconstruct the object.
Key Features and Concepts:
* Serialization: The process of converting a PHP object into a string representation (e.g., JSON).
* Denormalization: The process of converting a string representation (e.g., JSON) back into a PHP object.
* Context: Both normalization and denormalization can be controlled using an optional "context" array. This allows you to pass options that modify behavior, such as:
* `groups`: To serialize only specific properties of an object (often used in conjunction with `#[Groups]` attributes on properties).
* `enable_max_depth`: To limit the depth of an object graph during serialization, preventing infinite loops (circular references).
* `datetime_format`: To specify the output or input format for `DateTime` objects.
* `ignored_attributes`: To explicitly exclude certain properties from serialization.
* `circular_reference_handler`: A callable to handle circular references in a custom way.
* Custom Normalizers/Encoders: You can create your own normalizers and encoders to handle specific custom data types or formats not covered by the built-in ones.
* Attributes/Annotations: Symfony's serializer leverages PHP attributes (or Doctrine annotations in older versions) to configure serialization behavior directly on your object properties, such as defining serialization groups (`#[Groups]`), ignoring properties (`#[Ignore]`), or mapping property names (`#[SerializedName]`).
Common Use Cases:
* Building RESTful APIs: Easily convert your Doctrine entities or Data Transfer Objects (DTOs) into JSON or XML responses.
* Message Queues: Serialize complex objects into messages that can be sent to and consumed by other services.
* Caching: Store object states in a cache in a standardized format like JSON.
* Configuration Files: Load and save application configuration data in formats like YAML.
The `symfony/serializer` component promotes a clean separation of concerns, allowing you to manage your application's internal object structure independently from its external data representation.
Example Code
<?php
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;
// 1. Define a simple PHP class to serialize/denormalize
// For proper denormalization, properties typically need to be public,
// or have setters, or the ObjectNormalizer needs to use reflection (default behavior).
class Post
{
private int $id;
private string $title;
private string $content;
private string $author;
private \DateTimeImmutable $createdAt;
public function __construct(int $id, string $title, string $content, string $author, \DateTimeImmutable $createdAt)
{
$this->id = $id;
$this->title = $title;
$this->content = $content;
$this->author = $author;
$this->createdAt = $createdAt;
}
// Getters (required for serialization, as ObjectNormalizer reads public properties or via getters)
public function getId(): int { return $this->id; }
public function getTitle(): string { return $this->title; }
public function getContent(): string { return $this->content; }
public function getAuthor(): string { return $this->author; }
public function getCreatedAt(): \DateTimeImmutable { return $this->createdAt; }
// Setters (useful for denormalization, though ObjectNormalizer can use reflection to set private properties)
public function setId(int $id): void { $this->id = $id; }
public function setTitle(string $title): void { $this->title = $title; }
public function setContent(string $content): void { $this->content = $content; }
public function setAuthor(string $author): void { $this->author = $author; }
public function setCreatedAt(\DateTimeImmutable $createdAt): void { $this->createdAt = $createdAt; }
}
// 2. Configure the Serializer
// Order matters: more specific normalizers (like DateTimeNormalizer) should come before generic ones (like ObjectNormalizer).
$normalizers = [
new DateTimeNormalizer([
DateTimeNormalizer::FORMAT_KEY => \DateTimeImmutable::ATOM,
DateTimeNormalizer::DENORMALIZATION_FORMAT_KEY => \DateTimeImmutable::ATOM, // Default format for denormalization
]),
new ObjectNormalizer(),
];
$encoders = [new JsonEncoder()];
$serializer = new Serializer($normalizers, $encoders);
echo "=========================================\n";
echo " Symfony Serializer Example\n";
echo "=========================================\n\n";
// 3. --- Serialization Example (Object to JSON) ---
echo "--- Serialization ---\n";
$post = new Post(
1,
'Hello World',
'This is a test post about Symfony Serializer.',
'John Doe',
new \DateTimeImmutable()
);
// Serialize the object to JSON with a specific context (e.g., exclude 'author' property)
$jsonContentFiltered = $serializer->serialize($post, 'json', [
ObjectNormalizer::IGNORED_ATTRIBUTES => ['author'],
]);
echo "Serialized JSON (excluding author):\n";
echo $jsonContentFiltered . "\n\n";
// Serialize the object to JSON without any specific context
$jsonContentFull = $serializer->serialize($post, 'json');
echo "Full Serialized JSON:\n";
echo $jsonContentFull . "\n\n";
// 4. --- Denormalization Example (JSON to Object) ---
echo "--- Denormalization ---\n";
$jsonToDenormalize = '{"id":2,"title":"Another Post","content":"Content for another post.","author":"Jane Smith","createdAt":"2023-10-27T10:30:00+00:00"}';
// Denormalize the JSON string back into a Post object
// The third argument specifies the target class type
$denormalizedPost = $serializer->denormalize($jsonToDenormalize, Post::class, 'json');
echo "Denormalized Post Object:\n";
echo "ID: " . $denormalizedPost->getId() . "\n";
echo "Title: " . $denormalizedPost->getTitle() . "\n";
echo "Content: " . $denormalizedPost->getContent() . "\n";
echo "Author: " . $denormalizedPost->getAuthor() . "\n";
echo "Created At: " . $denormalizedPost->getCreatedAt()->format('Y-m-d H:i:s') . "\n\n";
// Denormalization with custom date format in the input JSON
// We need to create a new DateTimeNormalizer with the expected denormalization format.
$jsonDifferentDateFormat = '{"id":3,"title":"Time Test","content":"Post with specific time format.","author":"Alice","createdAt":"2023-10-28 15:00:00"}';
$differentFormatNormalizers = [
new DateTimeNormalizer([
DateTimeNormalizer::FORMAT_KEY => 'Y-m-d H:i:s', // Output format for serialization
DateTimeNormalizer::DENORMALIZATION_FORMAT_KEY => 'Y-m-d H:i:s', // Input format for denormalization
]),
new ObjectNormalizer(),
];
$differentFormatSerializer = new Serializer($differentFormatNormalizers, $encoders);
$denormalizedPostWithContext = $differentFormatSerializer->denormalize($jsonDifferentDateFormat, Post::class, 'json');
echo "Denormalized Post with specific input date format:\n";
echo "ID: " . $denormalizedPostWithContext->getId() . "\n";
echo "Title: " . $denormalizedPostWithContext->getTitle() . "\n";
echo "Created At: " . $denormalizedPostWithContext->getCreatedAt()->format('Y-m-d H:i:s') . "\n";
?>








symfony/serializer