Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 96af30f

Browse filesBrowse files
committed
[Serializer] Rewrite AbstractObjectNormalizer::createChildContext() to use the provided cache_key from original context when creating child contexts
If the normalization starts with an initial 'cache_key' it is currently discarded when creating child contexts. This change fixes that. The main reason behind it is that if the client code sends a unique identifier (ApiPlatform injects the IRI) and we have a use case that iterates a big resultset we end up with a big private cache that quickly runs out of allowed memory. The solution should be to send a 'cache_key' which ignores the entire cache key calculation that hashes the context.
1 parent 914c288 commit 96af30f
Copy full SHA for 96af30f

File tree

2 files changed

+50
-12
lines changed
Filter options

2 files changed

+50
-12
lines changed

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php
+13-12Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,7 @@ public function supportsNormalization(mixed $data, string $format = null /* , ar
153153
*/
154154
public function normalize(mixed $object, string $format = null, array $context = [])
155155
{
156-
if (!isset($context['cache_key'])) {
157-
$context['cache_key'] = $this->getCacheKey($format, $context);
158-
}
156+
$context['cache_key'] = $this->getCacheKey($format, $context);
159157

160158
$this->validateCallbackContext($context);
161159

@@ -287,8 +285,6 @@ abstract protected function extractAttributes(object $object, string $format = n
287285

288286
/**
289287
* Gets the attribute value.
290-
*
291-
* @return mixed
292288
*/
293289
abstract protected function getAttributeValue(object $object, string $attribute, string $format = null, array $context = []);
294290

@@ -302,14 +298,9 @@ public function supportsDenormalization(mixed $data, string $type, string $forma
302298
return class_exists($type) || (interface_exists($type, false) && null !== $this->classDiscriminatorResolver?->getMappingForClass($type));
303299
}
304300

305-
/**
306-
* @return mixed
307-
*/
308301
public function denormalize(mixed $data, string $type, string $format = null, array $context = [])
309302
{
310-
if (!isset($context['cache_key'])) {
311-
$context['cache_key'] = $this->getCacheKey($format, $context);
312-
}
303+
$context['cache_key'] = $this->getCacheKey($format, $context);
313304

314305
$this->validateCallbackContext($context);
315306

@@ -734,7 +725,13 @@ private function isMaxDepthReached(array $attributesMetadata, string $class, str
734725
protected function createChildContext(array $parentContext, string $attribute, ?string $format): array
735726
{
736727
$context = parent::createChildContext($parentContext, $attribute, $format);
737-
$context['cache_key'] = $this->getCacheKey($format, $context);
728+
if (isset($context['cache_key'])) {
729+
if (false !== $context['cache_key']) {
730+
$context['cache_key'] .= '-'.$attribute;
731+
}
732+
} else {
733+
$context['cache_key'] = $this->getCacheKey($format, $context);
734+
}
738735

739736
return $context;
740737
}
@@ -746,6 +743,10 @@ protected function createChildContext(array $parentContext, string $attribute, ?
746743
*/
747744
private function getCacheKey(?string $format, array $context): bool|string
748745
{
746+
if (isset($context['cache_key'])) {
747+
return $context['cache_key'];
748+
}
749+
749750
foreach ($context[self::EXCLUDE_FROM_CACHE_KEY] ?? $this->defaultContext[self::EXCLUDE_FROM_CACHE_KEY] as $key) {
750751
unset($context[$key]);
751752
}

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php
+37Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -788,6 +788,43 @@ public function supportsNormalization(mixed $data, string $format = null, array
788788
$this->assertSame('called', $object->bar);
789789
}
790790

791+
public function testChildContextKeepsOriginalContextCacheKey()
792+
{
793+
$foobar = new Dummy();
794+
$foobar->foo = new EmptyDummy();
795+
$foobar->bar = 'bar';
796+
$foobar->baz = 'baz';
797+
$data = [
798+
'foo' => [],
799+
'bar' => 'bar',
800+
'baz' => 'baz',
801+
];
802+
803+
$normalizer = new class() extends AbstractObjectNormalizerDummy {
804+
protected function extractAttributes(object $object, string $format = null, array $context = []): array
805+
{
806+
return array_keys((array) $object);
807+
}
808+
809+
protected function getAttributeValue(object $object, string $attribute, string $format = null, array $context = []): mixed
810+
{
811+
return $object->{$attribute};
812+
}
813+
814+
protected function createChildContext(array $parentContext, string $attribute, ?string $format): array
815+
{
816+
$childContext = parent::createChildContext($parentContext, $attribute, $format);
817+
AbstractObjectNormalizerTest::assertSame('hardcoded-'.$attribute, $childContext['cache_key']);
818+
819+
return $childContext;
820+
}
821+
};
822+
823+
$serializer = new Serializer([$normalizer]);
824+
$normalizedObject = $serializer->normalize($foobar, null, ['cache_key' => 'hardcoded']);
825+
$this->assertSame($data, $normalizedObject);
826+
}
827+
791828
public function testDenormalizeUnionOfEnums()
792829
{
793830
$serializer = new Serializer([

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.