From 942a1845c1fd53b15650bde45c111edc3af33ed0 Mon Sep 17 00:00:00 2001 From: Alex Kalineskou Date: Fri, 14 Apr 2023 03:52:15 +0300 Subject: [PATCH] Fix serializer normalize attribute context --- .../Normalizer/AbstractObjectNormalizer.php | 9 +++--- .../AbstractObjectNormalizerTest.php | 29 +++++++++++++++++-- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php index 1feff46ad3d56..afd3acabc46a2 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php @@ -196,14 +196,14 @@ public function normalize(mixed $object, string $format = null, array $context = $attributeValue = $maxDepthHandler($attributeValue, $object, $attribute, $format, $attributeContext); } - $attributeValue = $this->applyCallbacks($attributeValue, $object, $attribute, $format, $attributeContext); - - $stack[$attribute] = $attributeValue; + $stack[$attribute] = $this->applyCallbacks($attributeValue, $object, $attribute, $format, $attributeContext); } foreach ($stack as $attribute => $attributeValue) { + $attributeContext = $this->getAttributeNormalizationContext($object, $attribute, $context); + if (null === $attributeValue || \is_scalar($attributeValue)) { - $data = $this->updateData($data, $attribute, $attributeValue, $class, $format, $context, $attributesMetadata, $classMetadata); + $data = $this->updateData($data, $attribute, $attributeValue, $class, $format, $attributeContext, $attributesMetadata, $classMetadata); continue; } @@ -211,7 +211,6 @@ public function normalize(mixed $object, string $format = null, array $context = throw new LogicException(sprintf('Cannot normalize attribute "%s" because the injected serializer is not a normalizer.', $attribute)); } - $attributeContext = $this->getAttributeNormalizationContext($object, $attribute, $context); $childContext = $this->createChildContext($attributeContext, $attribute, $format); $data = $this->updateData($data, $attribute, $this->serializer->normalize($attributeValue, $format, $childContext), $class, $format, $attributeContext, $attributesMetadata, $classMetadata); diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php index 9a319f7ef0b8a..0c342b64d8000 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php @@ -17,6 +17,7 @@ use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor; use Symfony\Component\PropertyInfo\PropertyInfoExtractor; use Symfony\Component\PropertyInfo\Type; +use Symfony\Component\Serializer\Annotation\Context; use Symfony\Component\Serializer\Annotation\SerializedName; use Symfony\Component\Serializer\Annotation\SerializedPath; use Symfony\Component\Serializer\Exception\ExtraAttributesException; @@ -549,13 +550,28 @@ public function testNormalizeUsesContextAttributeForPropertiesInConstructorWithS $extractor = new PropertyInfoExtractor([], [new PhpDocExtractor(), new ReflectionExtractor()]); $normalizer = new ObjectNormalizer($classMetadataFactory, new MetadataAwareNameConverter($classMetadataFactory), null, $extractor); - $serializer = new Serializer([new DateTimeNormalizer([DateTimeNormalizer::FORMAT_KEY => 'd-m-Y']), $normalizer]); + $serializer = new Serializer([new DateTimeNormalizer(), $normalizer]); $obj = new ObjectDummyWithContextAttributeAndSerializedPath(new \DateTimeImmutable('22-02-2023')); $data = $serializer->normalize($obj); - $this->assertSame(['property' => ['with_path' => '22-02-2023']], $data); + $this->assertSame(['property' => ['with_path' => '02-22-2023']], $data); + } + + public function testNormalizeUsesContextAttributeForProperties() + { + $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader())); + + $extractor = new PropertyInfoExtractor([], [new PhpDocExtractor(), new ReflectionExtractor()]); + $normalizer = new ObjectNormalizer($classMetadataFactory, new MetadataAwareNameConverter($classMetadataFactory), null, $extractor); + $serializer = new Serializer([$normalizer]); + + $obj = new ObjectDummyWithContextAttributeSkipNullValues(); + + $data = $serializer->normalize($obj); + + $this->assertSame(['propertyWithoutNullSkipNullValues' => 'foo'], $data); } } @@ -668,6 +684,15 @@ public function __construct( } } +class ObjectDummyWithContextAttributeSkipNullValues +{ + #[Context([AbstractObjectNormalizer::SKIP_NULL_VALUES => true])] + public ?string $propertyWithoutNullSkipNullValues = 'foo'; + + #[Context([AbstractObjectNormalizer::SKIP_NULL_VALUES => true])] + public ?string $propertyWithNullSkipNullValues = null; +} + class AbstractObjectNormalizerWithMetadata extends AbstractObjectNormalizer { public function __construct()