@@ -94,7 +94,7 @@ public function normalize($object, $format = null, array $context = [])
94
94
throw new LogicException (sprintf ('Cannot normalize attribute "%s" because the injected serializer is not a normalizer ' , $ attribute ));
95
95
}
96
96
97
- $ data = $ this ->updateData ($ data , $ attribute , $ this ->serializer ->normalize ($ attributeValue , $ format , $ this ->createChildContext ($ context , $ attribute )));
97
+ $ data = $ this ->updateData ($ data , $ attribute , $ this ->serializer ->normalize ($ attributeValue , $ format , $ this ->createChildContext ($ context , $ attribute, $ format )));
98
98
}
99
99
100
100
return $ data ;
@@ -128,15 +128,13 @@ protected function getAttributes($object, $format = null, array $context)
128
128
return $ allowedAttributes ;
129
129
}
130
130
131
- if (isset ($ context ['attributes ' ])) {
132
- return $ this ->extractAttributes ($ object , $ format , $ context );
133
- }
131
+ $ attributes = $ this ->extractAttributes ($ object , $ format , $ context );
134
132
135
- if (isset ( $ this -> attributesCache [ $ class ]) ) {
136
- return $ this ->attributesCache [$ class ] ;
133
+ if ($ context [ ' cache_key ' ] ) {
134
+ $ this ->attributesCache [$ key ] = $ attributes ;
137
135
}
138
136
139
- return $ this -> attributesCache [ $ class ] = $ this -> extractAttributes ( $ object , $ format , $ context ) ;
137
+ return $ attributes ;
140
138
}
141
139
142
140
/**
@@ -276,7 +274,7 @@ private function validateAndDenormalize($currentClass, $attribute, $data, $forma
276
274
throw new LogicException (sprintf ('Cannot denormalize attribute "%s" for class "%s" because injected serializer is not a denormalizer ' , $ attribute , $ class ));
277
275
}
278
276
279
- $ childContext = $ this ->createChildContext ($ context , $ attribute );
277
+ $ childContext = $ this ->createChildContext ($ context , $ attribute, $ format );
280
278
if ($ this ->serializer ->supportsDenormalization ($ data , $ class , $ format , $ childContext )) {
281
279
return $ this ->serializer ->denormalize ($ data , $ class , $ format , $ childContext );
282
280
}
@@ -373,7 +371,32 @@ private function isMaxDepthReached(array $attributesMetadata, $class, $attribute
373
371
}
374
372
375
373
/**
376
- * Gets the cache key to use.
374
+ * Overwritten to update the cache key for the child.
375
+ *
376
+ * We must not mix up the attribute cache between parent and children.
377
+ *
378
+ * {@inheritdoc}
379
+ */
380
+ protected function createChildContext (array $ parentContext , $ attribute/*, string $format = null */ )
381
+ {
382
+ if (\func_num_args () >= 3 ) {
383
+ $ format = \func_get_arg (2 );
384
+ } else {
385
+ // will be deprecated in version 4
386
+ $ format = null ;
387
+ }
388
+
389
+ $ context = parent ::createChildContext ($ parentContext , $ attribute , $ format );
390
+ // format is already included in the cache_key of the parent.
391
+ $ context ['cache_key ' ] = $ this ->getCacheKey ($ format , $ context );
392
+
393
+ return $ context ;
394
+ }
395
+
396
+ /**
397
+ * Builds the cache key for the attributes cache.
398
+ *
399
+ * The key must be different for every option in the context that could change which attributes should be handled.
377
400
*
378
401
* @param string|null $format
379
402
* @param array $context
@@ -382,8 +405,13 @@ private function isMaxDepthReached(array $attributesMetadata, $class, $attribute
382
405
*/
383
406
private function getCacheKey ($ format , array $ context )
384
407
{
408
+ unset($ context ['cache_key ' ]); // avoid artificially different keys
385
409
try {
386
- return md5 ($ format .serialize ($ context ));
410
+ return md5 ($ format .serialize ([
411
+ 'context ' => $ context ,
412
+ 'ignored ' => $ this ->ignoredAttributes ,
413
+ 'camelized ' => $ this ->camelizedAttributes ,
414
+ ]));
387
415
} catch (\Exception $ exception ) {
388
416
// The context cannot be serialized, skip the cache
389
417
return false ;
0 commit comments