@@ -334,7 +334,8 @@ protected function instantiateObject(array &$data, string $class, array &$contex
334334 $ params = [];
335335 foreach ($ constructorParameters as $ constructorParameter ) {
336336 $ paramName = $ constructorParameter ->name ;
337- $ key = $ this ->nameConverter ? $ this ->nameConverter ->normalize ($ paramName , $ class , $ format , $ context ) : $ paramName ;
337+ $ attributeContext = $ this ->getAttributeDenormalizationContext ($ class , $ paramName , $ context );
338+ $ key = $ this ->nameConverter ? $ this ->nameConverter ->normalize ($ paramName , $ class , $ format , $ attributeContext ) : $ paramName ;
338339
339340 $ allowed = false === $ allowedAttributes || \in_array ($ paramName , $ allowedAttributes );
340341 $ ignored = !$ this ->isAllowedAttribute ($ class , $ paramName , $ format , $ context );
@@ -346,7 +347,7 @@ protected function instantiateObject(array &$data, string $class, array &$contex
346347
347348 $ variadicParameters = [];
348349 foreach ($ data [$ paramName ] as $ parameterData ) {
349- $ variadicParameters [] = $ this ->denormalizeParameter ($ reflectionClass , $ constructorParameter , $ paramName , $ parameterData , $ context , $ format );
350+ $ variadicParameters [] = $ this ->denormalizeParameter ($ reflectionClass , $ constructorParameter , $ paramName , $ parameterData , $ attributeContext , $ format );
350351 }
351352
352353 $ params = array_merge ($ params , $ variadicParameters );
@@ -363,7 +364,7 @@ protected function instantiateObject(array &$data, string $class, array &$contex
363364
364365 // Don't run set for a parameter passed to the constructor
365366 try {
366- $ params [] = $ this ->denormalizeParameter ($ reflectionClass , $ constructorParameter , $ paramName , $ parameterData , $ context , $ format );
367+ $ params [] = $ this ->denormalizeParameter ($ reflectionClass , $ constructorParameter , $ paramName , $ parameterData , $ attributeContext , $ format );
367368 } catch (NotNormalizableValueException $ exception ) {
368369 if (!isset ($ context ['not_normalizable_value_exceptions ' ])) {
369370 throw $ exception ;
@@ -485,4 +486,43 @@ final protected function applyCallbacks(mixed $value, object|string $object, str
485486
486487 return $ callback ? $ callback ($ value , $ object , $ attribute , $ format , $ context ) : $ value ;
487488 }
489+
490+ /**
491+ * Computes the normalization context merged with current one. Metadata always wins over global context, as more specific.
492+ *
493+ * @internal
494+ */
495+ protected function getAttributeNormalizationContext (object $ object , string $ attribute , array $ context ): array
496+ {
497+ if (null === $ metadata = $ this ->getAttributeMetadata ($ object , $ attribute )) {
498+ return $ context ;
499+ }
500+
501+ return array_merge ($ context , $ metadata ->getNormalizationContextForGroups ($ this ->getGroups ($ context )));
502+ }
503+
504+ /**
505+ * Computes the denormalization context merged with current one. Metadata always wins over global context, as more specific.
506+ *
507+ * @internal
508+ */
509+ protected function getAttributeDenormalizationContext (string $ class , string $ attribute , array $ context ): array
510+ {
511+ $ context ['deserialization_path ' ] = ($ context ['deserialization_path ' ] ?? false ) ? $ context ['deserialization_path ' ].'. ' .$ attribute : $ attribute ;
512+
513+ if (null === $ metadata = $ this ->getAttributeMetadata ($ class , $ attribute )) {
514+ return $ context ;
515+ }
516+
517+ return array_merge ($ context , $ metadata ->getDenormalizationContextForGroups ($ this ->getGroups ($ context )));
518+ }
519+
520+ private function getAttributeMetadata ($ objectOrClass , string $ attribute ): ?AttributeMetadataInterface
521+ {
522+ if (!$ this ->classMetadataFactory ) {
523+ return null ;
524+ }
525+
526+ return $ this ->classMetadataFactory ->getMetadataFor ($ objectOrClass )->getAttributesMetadata ()[$ attribute ] ?? null ;
527+ }
488528}
0 commit comments