Skip to content

Commit 531fb00

Browse files
bug #50015 [Serializer] Fix serializer normalize attribute context (akalineskou)
This PR was merged into the 6.2 branch. Discussion ---------- [Serializer] Fix serializer normalize attribute context | Q | A | ------------- | --- | Branch? | 6.2 <!-- see below --> | Bug fix? | yes | New feature? | no <!-- please update src/**/CHANGELOG.md files --> | Deprecations? | no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files --> | Tickets | Fix #... <!-- prefix each issue number with "Fix #", no need to create an issue if none exists, explain below instead --> | License | MIT | Doc PR | symfony/symfony-docs#... <!-- required for new features --> <!-- Replace this notice by a short README for your feature/bugfix. This will help reviewers and should be a good start for the documentation. Additionally (see https://symfony.com/releases): - Always add tests and ensure they pass. - Bug fixes must be submitted against the lowest maintained branch where they apply (lowest branches are regularly merged to upper ones so they get the fixes too). - Features and deprecations must be submitted against the latest branch. - For new features, provide some code snippets to help understand usage. - Changelog entry should follow https://symfony.com/doc/current/contributing/code/conventions.html#writing-a-changelog-entry - Never break backward compatibility (see https://symfony.com/bc). --> Before 6.2.8 property attribute`#[Context(normalizationContext: [AbstractObjectNormalizer::SKIP_NULL_VALUES => true])]` was working correctly Before this PR #49525 `updateData` was using the `$attributeContext` but it got changed to using `$context` (which ignored the attribute context) Fixed the `testNormalizeUsesContextAttributeForPropertiesInConstructorWithSerializedPath` test also since `Context` attribute class was never used in the file (the date was still in `d-m-Y` format when the format key was `m-d-Y`) Would have ported it to 5.4, but it was not added in that branch. Latest commit for this file in 5.4 https://github.com/symfony/symfony/blob/6ae4ac9b9f46203b3ebae3c4c52edd546709bdb1/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php#L205 Commits ------- 942a184 Fix serializer normalize attribute context
2 parents 0a1c1f4 + 942a184 commit 531fb00

File tree

2 files changed

+31
-7
lines changed

2 files changed

+31
-7
lines changed

src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -196,22 +196,21 @@ public function normalize(mixed $object, string $format = null, array $context =
196196
$attributeValue = $maxDepthHandler($attributeValue, $object, $attribute, $format, $attributeContext);
197197
}
198198

199-
$attributeValue = $this->applyCallbacks($attributeValue, $object, $attribute, $format, $attributeContext);
200-
201-
$stack[$attribute] = $attributeValue;
199+
$stack[$attribute] = $this->applyCallbacks($attributeValue, $object, $attribute, $format, $attributeContext);
202200
}
203201

204202
foreach ($stack as $attribute => $attributeValue) {
203+
$attributeContext = $this->getAttributeNormalizationContext($object, $attribute, $context);
204+
205205
if (null === $attributeValue || \is_scalar($attributeValue)) {
206-
$data = $this->updateData($data, $attribute, $attributeValue, $class, $format, $context, $attributesMetadata, $classMetadata);
206+
$data = $this->updateData($data, $attribute, $attributeValue, $class, $format, $attributeContext, $attributesMetadata, $classMetadata);
207207
continue;
208208
}
209209

210210
if (!$this->serializer instanceof NormalizerInterface) {
211211
throw new LogicException(sprintf('Cannot normalize attribute "%s" because the injected serializer is not a normalizer.', $attribute));
212212
}
213213

214-
$attributeContext = $this->getAttributeNormalizationContext($object, $attribute, $context);
215214
$childContext = $this->createChildContext($attributeContext, $attribute, $format);
216215

217216
$data = $this->updateData($data, $attribute, $this->serializer->normalize($attributeValue, $format, $childContext), $class, $format, $attributeContext, $attributesMetadata, $classMetadata);

src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
1818
use Symfony\Component\PropertyInfo\PropertyInfoExtractor;
1919
use Symfony\Component\PropertyInfo\Type;
20+
use Symfony\Component\Serializer\Annotation\Context;
2021
use Symfony\Component\Serializer\Annotation\SerializedName;
2122
use Symfony\Component\Serializer\Annotation\SerializedPath;
2223
use Symfony\Component\Serializer\Exception\ExtraAttributesException;
@@ -549,13 +550,28 @@ public function testNormalizeUsesContextAttributeForPropertiesInConstructorWithS
549550

550551
$extractor = new PropertyInfoExtractor([], [new PhpDocExtractor(), new ReflectionExtractor()]);
551552
$normalizer = new ObjectNormalizer($classMetadataFactory, new MetadataAwareNameConverter($classMetadataFactory), null, $extractor);
552-
$serializer = new Serializer([new DateTimeNormalizer([DateTimeNormalizer::FORMAT_KEY => 'd-m-Y']), $normalizer]);
553+
$serializer = new Serializer([new DateTimeNormalizer(), $normalizer]);
553554

554555
$obj = new ObjectDummyWithContextAttributeAndSerializedPath(new \DateTimeImmutable('22-02-2023'));
555556

556557
$data = $serializer->normalize($obj);
557558

558-
$this->assertSame(['property' => ['with_path' => '22-02-2023']], $data);
559+
$this->assertSame(['property' => ['with_path' => '02-22-2023']], $data);
560+
}
561+
562+
public function testNormalizeUsesContextAttributeForProperties()
563+
{
564+
$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
565+
566+
$extractor = new PropertyInfoExtractor([], [new PhpDocExtractor(), new ReflectionExtractor()]);
567+
$normalizer = new ObjectNormalizer($classMetadataFactory, new MetadataAwareNameConverter($classMetadataFactory), null, $extractor);
568+
$serializer = new Serializer([$normalizer]);
569+
570+
$obj = new ObjectDummyWithContextAttributeSkipNullValues();
571+
572+
$data = $serializer->normalize($obj);
573+
574+
$this->assertSame(['propertyWithoutNullSkipNullValues' => 'foo'], $data);
559575
}
560576
}
561577

@@ -668,6 +684,15 @@ public function __construct(
668684
}
669685
}
670686

687+
class ObjectDummyWithContextAttributeSkipNullValues
688+
{
689+
#[Context([AbstractObjectNormalizer::SKIP_NULL_VALUES => true])]
690+
public ?string $propertyWithoutNullSkipNullValues = 'foo';
691+
692+
#[Context([AbstractObjectNormalizer::SKIP_NULL_VALUES => true])]
693+
public ?string $propertyWithNullSkipNullValues = null;
694+
}
695+
671696
class AbstractObjectNormalizerWithMetadata extends AbstractObjectNormalizer
672697
{
673698
public function __construct()

0 commit comments

Comments
 (0)