Installation Add the bundle via Composer:
composer require jms/serializer-bundle
Register the bundle in config/bundles.php (Symfony 4+):
return [
// ...
JMS\SerializerBundle\JMSSerializerBundle::class => ['all' => true],
];
First Use Case Serialize an object to JSON in a controller:
use JMS\Serializer\SerializerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
class MyController extends AbstractController
{
public function show(MyEntity $entity, SerializerInterface $serializer): JsonResponse
{
return new JsonResponse($serializer->serialize($entity, 'json'));
}
}
Where to Look First
config/packages/jms_serializer.yaml (auto-generated)@SerializedName, @Groups, @ExclusionPolicySerialization
$serializer->serialize($data, 'json')$serializer->serialize($data, 'json', ['groups' => ['group1', 'group2']])config/packages/jms_serializer.yaml:
jms_serializer:
handlers:
datetime:
default_strategy: ~
Deserialization
$serializer->deserialize($json, 'App\Entity\MyEntity', 'json')['groups' => ['group1']]).Entity Serialization
jms_serializer:
metadata:
directories:
App\Entity:
namespace_prefix: "App\\Entity"
path: "%kernel.project_dir%/config/serializer"
App\Entity\MyEntity.yaml):
App\Entity\MyEntity:
exclusion_policy: ALL
properties:
id:
expose: true
groups: [Default]
name:
expose: true
groups: [Default, Detail]
API Responses
SerializerAwareTrait or inject SerializerInterface:
use JMS\Serializer\SerializerInterface;
public function __construct(private SerializerInterface $serializer) {}
public function show(MyEntity $entity): JsonResponse
{
return new JsonResponse($this->serializer->serialize($entity, 'json', ['groups' => ['api']]));
}
FOS\RestBundle\View\View:
return $this->view($entity, 200, [], ['groups' => ['api']]);
Custom Handlers
DateTime):
jms_serializer:
handlers:
datetime:
default_strategy: "App\Serializer\Handler\DateTimeHandler"
JMS\Serializer\Handler\SubscribingHandlerInterface:
class CustomHandler implements SubscribingHandlerInterface
{
public static function getSubscribingMethods()
{
return [
[
'direction' => SerializationDirection::DESERIALIZATION,
'format' => 'json',
'type' => 'App\Entity\MyEntity',
'method' => 'deserializeMyEntity',
],
];
}
public function deserializeMyEntity(DeserializationContext $context)
{
// Custom logic
}
}
Event Listeners
JMS\Serializer\EventDispatcher\ObjectEvent:
use JMS\Serializer\EventDispatcher\ObjectEvent;
$dispatcher->addSubscriber(new class() {
public function onPostSerialize(ObjectEvent $event)
{
if ($event->getObject() instanceof MyEntity) {
$event->getVisitor()->addData(['custom_field' => 'value']);
}
}
});
Doctrine Integration
jms_serializer:
metadata:
directories:
App\Entity:
namespace_prefix: "App\\Entity"
path: "%kernel.project_dir%/config/serializer"
type: "yaml"
php bin/console jms:serializer:update
Symfony Forms
JMS\Serializer\SerializationContext with forms:
$context = SerializationContext::create()
->setGroups(['form'])
->setSerializeNull(true);
$serializer->serialize($form, 'json', $context);
API Versioning
// Entity annotation
/** @Groups({"api_v1", "api_v2"}) */
private $id;
/** @Groups({"api_v2"}) */
private $newField;
// Controller
$serializer->serialize($entity, 'json', ['groups' => ['api_v1']]);
Caching
jms_serializer:
metadata:
cache: "file" # or "apcu", "memcache"
cache_dir: "%kernel.project_dir%/var/cache/jms_serializer"
Circular References
@MaxDepth annotation or configure max depth in context:
$context = SerializationContext::create()->setMaxDepth(2);
Null Values
serialize_null in config/packages/jms_serializer.yaml:
jms_serializer:
handlers:
JMS\Serializer\Handler\ArrayHandler:
serialize_null: true
['serialize_null' => true] to the serializer.Doctrine Proxy Objects
@ExclusionPolicy(ExclusionPolicy::ALL) and manually expose required fields.Type Mismatches
@Type annotation or custom handlers:
/** @Type("string") */
private $id;
Configuration Overrides
$serializer->serialize($data, 'json', ['groups' => ['custom']]);
XML Serialization
format_output:
jms_serializer:
handlers:
JMS\Serializer\Handler\XmlHandler:
format_output: true
Symfony 4+ Autowiring
SerializerInterface not autowired.config/bundles.php and use:
use JMS\Serializer\SerializerInterface;
Enable Debug Mode
JMS_SERIALIZER_DEBUG environment variable to log serialization issues.Check Metadata
php bin/console debug:container jms_serializer.metadata.directory.App_Entity
Inspect Context
$context = SerializationContext::create()->setGroups(['debug']);
$serializer->serialize($data, 'json', $context);
Handle Exceptions
JMS\Serializer\Exception\RuntimeException for runtime errors:
try {
$serializer->serialize($data, 'json');
} catch (\Exception $e) {
// Log or handle error
}
# config/serializer/App\Entity/MyEntity.yaml
App\Entity\MyEntity:
properties:
How can I help you explore Laravel packages today?