diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php index a2eb65ca5bc6f..5a8ac29ebe36d 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php @@ -302,9 +302,6 @@ public function supportsDenormalization(mixed $data, string $type, string $forma return class_exists($type) || (interface_exists($type, false) && null !== $this->classDiscriminatorResolver?->getMappingForClass($type)); } - /** - * @return mixed - */ public function denormalize(mixed $data, string $type, string $format = null, array $context = []) { if (!isset($context['cache_key'])) { @@ -734,7 +731,13 @@ private function isMaxDepthReached(array $attributesMetadata, string $class, str protected function createChildContext(array $parentContext, string $attribute, ?string $format): array { $context = parent::createChildContext($parentContext, $attribute, $format); - $context['cache_key'] = $this->getCacheKey($format, $context); + if (isset($context['cache_key'])) { + if (false !== $context['cache_key']) { + $context['cache_key'] .= '-'.$attribute; + } + } else { + $context['cache_key'] = $this->getCacheKey($format, $context); + } return $context; } diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php index 13a34fa233457..5a5cc282fdbd8 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php @@ -788,6 +788,46 @@ public function supportsNormalization(mixed $data, string $format = null, array $this->assertSame('called', $object->bar); } + public function testChildContextKeepsOriginalContextCacheKey() + { + $foobar = new Dummy(); + $foobar->foo = new EmptyDummy(); + $foobar->bar = 'bar'; + $foobar->baz = 'baz'; + $data = [ + 'foo' => [], + 'bar' => 'bar', + 'baz' => 'baz', + ]; + + $normalizer = new class() extends AbstractObjectNormalizerDummy { + public ?string $childContextCacheKey = null; + + protected function extractAttributes(object $object, string $format = null, array $context = []): array + { + return array_keys((array) $object); + } + + protected function getAttributeValue(object $object, string $attribute, string $format = null, array $context = []): mixed + { + return $object->{$attribute}; + } + + protected function createChildContext(array $parentContext, string $attribute, ?string $format): array + { + $childContext = parent::createChildContext($parentContext, $attribute, $format); + $this->childContextCacheKey = $childContext['cache_key']; + + return $childContext; + } + }; + + $serializer = new Serializer([$normalizer]); + $normalizedObject = $serializer->normalize($foobar, null, ['cache_key' => 'hardcoded']); + // $this->assertSame($data, $normalizedObject); + $this->assertSame('hardcoded-foo', $normalizer->childContextCacheKey); + } + public function testDenormalizeUnionOfEnums() { $serializer = new Serializer([