Installation
composer require symfony/serializer-pack
This auto-installs symfony/serializer and its dependencies (symfony/yaml, symfony/property-access, etc.).
Basic Usage
Register the serializer in config/services.php:
$container->register('serializer', \Symfony\Component\Serializer\Serializer::class)
->setArguments([
[new \Symfony\Component\Serializer\Encoder\JsonEncoder(), new \Symfony\Component\Serializer\Encoder\XmlEncoder()],
[new \Symfony\Component\Serializer\Normalizer\ObjectNormalizer(), new \Symfony\Component\Serializer\Normalizer\DateTimeNormalizer()]
]);
First Serialization
$serializer = app('serializer');
$data = $serializer->serialize($object, 'json');
$decoded = $serializer->deserialize($data, Object::class, 'json');
Key Files to Review
config/packages/serializer.yaml (auto-generated by the pack)src/Serializer/ (if extending default behavior)ObjectNormalizer with ignoredAttributes to exclude sensitive fields:
# config/packages/serializer.yaml
framework:
serializer:
normalizers:
App\Dto\UserDto:
ignored_attributes: ['password', 'apiToken']
enable_max_depth in ObjectNormalizer:
$normalizer = new ObjectNormalizer(['enable_max_depth' => true]);
ObjectNormalizer for domain-specific logic:
use Symfony\Component\Serializer\Normalizer\ContextAwareNormalizerInterface;
class UserNormalizer implements ContextAwareNormalizerInterface {
public function normalize($object, $format = null, array $context = []) {
return [
'id' => $object->id,
'email' => $object->email,
'roles' => $object->getRoles()->toArray(),
];
}
// ... implement other required methods
}
serializer.yaml:
framework:
serializer:
normalizers:
App\Normalizer\UserNormalizer: ~
SerializerContextBuilder to pass metadata:
use Symfony\Component\Serializer\SerializerInterface;
use ApiPlatform\Core\Serializer\SerializerContextBuilderInterface;
class CustomContextBuilder implements SerializerContextBuilderInterface {
public function createFromRequest(Request $request, bool $normalization, array $extractedAttributes = null) {
$context = parent::createFromRequest($request, $normalization, $extractedAttributes);
$context['groups'] = ['api']; // Use groups for granular control
return $context;
}
}
SerializerEventDispatcher:
$dispatcher = new SerializerEventDispatcher($serializer);
$dispatcher->addSubscriber(new class implements SerializerSubscriberInterface {
public function onSerialize(SerializeEvent $event) {
if ($event->getData() instanceof User) {
$event->setData($this->sanitizeUser($event->getData()));
}
}
});
SerializerInterface mock in PHPUnit:
$mockSerializer = $this->createMock(SerializerInterface::class);
$mockSerializer->method('serialize')->willReturn(json_encode(['id' => 1]));
$this->app->instance(SerializerInterface::class, $mockSerializer);
Performance Overhead
enable_max_depth and max_depth in ObjectNormalizer:
framework:
serializer:
normalizers:
Symfony\Component\Serializer\Normalizer\ObjectNormalizer:
max_depth: 3
DateTime Handling
DateTimeNormalizer uses ISO format, which may not match API expectations.framework:
serializer:
normalizers:
Symfony\Component\Serializer\Normalizer\DateTimeNormalizer:
format: 'Y-m-d H:i:s'
Circular References
CircularReferenceException.enable_max_depth or use DenormalizerInterface with custom logic.Group-Based Normalization
@Groups({"api"}) to properties breaks group-based serialization.App\Entity\User:
attributes:
email:
groups: ['api']
Type Safety
denormalize() with strict type checks:
$user = $serializer->deserialize($data, User::class, 'json', [
'object_to_populate' => new User(), // Pre-instantiate
]);
Inspect Context
Use SerializerContextBuilder to log context:
$context = $serializer->getContext();
\Log::debug('Serialization context:', $context);
Normalizer Debugging
Enable debug mode in ObjectNormalizer:
$normalizer = new ObjectNormalizer(['debug' => true]);
Encoder Issues
json_last_error().SimpleXMLElement to validate output.Custom Encoders
Extend EncoderInterface for formats like CSV or MessagePack:
class CsvEncoder implements EncoderInterface {
public function encode($data, $format, array $context = []) {
// Custom CSV logic
}
public function supportsEncoding($format) { return 'csv' === $format; }
}
Dynamic Normalizers
Use NormalizerAwareInterface for runtime normalizer selection:
class DynamicNormalizer implements NormalizerInterface, NormalizerAwareInterface {
public function setNormalizers(array $normalizers) {
$this->normalizers = $normalizers;
}
public function normalize($object, $format = null, array $context = []) {
// Delegate to registered normalizers
}
}
Symfony Messenger Integration
Serialize messages with SerializerInterface:
$serialized = $serializer->serialize($message, 'json');
$bus->dispatch(new AsyncMessage($serialized));
Cache Normalization Results
Use CacheNormalizer to cache serialized data:
framework:
serializer:
normalizers:
Symfony\Component\Serializer\Normalizer\CacheNormalizer:
cache_pool: cache.app
ttl: 3600
How can I help you explore Laravel packages today?