I have app based on symfony5.4. Inside this app I have a class for client like this:
class Client
{
#[Context([DateTimeNormalizer::FORMAT_KEY => 'Y-m-d'])]
public \DateTimeImmutable $passportIssuedDate;
#[Context([DateTimeNormalizer::FORMAT_KEY => \DateTimeImmutable::ATOM])]
public \DateTimeImmutable $agreementDateTime;
}
There is custom serializer:
$encoders = [new JsonEncoder()];
$extractor = new PropertyInfoExtractor([], [new PhpDocExtractor(), new ReflectionExtractor()]);
$normalizers = [
new DateTimeNormalizer(),
new ObjectNormalizer(propertyTypeExtractor: $extractor),
];
$serializer = new Serializer($normalizers, $encoders);
If I call standard autowired serializer
$this->serializer->serialize($client, 'json');
I get this result
{"passportIssuedDate":"2024-04-05","agreementDateTime":"2024-04-05T11:59:32+00:00"}
But in case of custom one I see this:
{"passportIssuedDate":"2024-04-05T11:59:32+00:00","agreementDateTime":"2024-04-05T11:59:32+00:00"}
How I need to change my custom serializer to handle Context attributes properly?
When you create your ObjectNormalizer
, you need to pass a ClassMetadataFactory
created from an AttributeLoader
:
require('vendor/autoload.php');
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Annotation\Context;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
use Symfony\Component\Serializer\Mapping\Loader\AttributeLoader;
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
class Client
{
#[Context([DateTimeNormalizer::FORMAT_KEY => 'Y-m-d'])]
public \DateTimeImmutable $passportIssuedDate;
#[Context([DateTimeNormalizer::FORMAT_KEY => \DateTimeImmutable::ATOM])]
public \DateTimeImmutable $agreementDateTime;
}
$encoders = [new JsonEncoder()];
$extractor = new ReflectionExtractor();
$classMetadataFactory = new ClassMetadataFactory(new AttributeLoader());
$normalizers = [
new DateTimeNormalizer(),
new ObjectNormalizer($classMetadataFactory, null, null, $extractor),
];
$serializer = new Serializer($normalizers, $encoders);
$client = new Client();
$client->passportIssuedDate = new DateTimeImmutable('2024-04-05');
$client->agreementDateTime = new DateTimeImmutable('2024-04-05');
echo $serializer->serialize($client, 'json');
Output:
{"passportIssuedDate":"2024-04-05","agreementDateTime":"2024-04-05T00:00:00+00:00"}