@@ -35,6 +35,9 @@ final class MetadataHydrator implements Hydrator
3535 /** @var array<int, class-string> */
3636 private array $ stack = [];
3737
38+ /** @var array<class-string, ClassMetadata> */
39+ private array $ classMetadata = [];
40+
3841 public function __construct (
3942 private readonly MetadataFactory $ metadataFactory = new AttributeMetadataFactory (),
4043 PayloadCryptographer |null $ cryptographer = null ,
@@ -65,7 +68,7 @@ public function __construct(
6568 public function hydrate (string $ class , array $ data ): object
6669 {
6770 try {
68- $ metadata = $ this ->metadataFactory -> metadata ($ class );
71+ $ metadata = $ this ->metadata ($ class );
6972 } catch (ClassNotFound $ e ) {
7073 throw new ClassNotSupported ($ class , $ e );
7174 }
@@ -132,10 +135,6 @@ private function doHydrate(ClassMetadata $metadata, array $data): object
132135 $ normalizer = $ propertyMetadata ->normalizer ;
133136
134137 if ($ normalizer ) {
135- if ($ normalizer instanceof HydratorAwareNormalizer) {
136- $ normalizer ->setHydrator ($ this );
137- }
138-
139138 try {
140139 /** @psalm-suppress MixedAssignment */
141140 $ value = $ normalizer ->denormalize ($ value );
@@ -182,7 +181,7 @@ public function extract(object $object): array
182181 $ this ->stack [$ objectId ] = $ object ::class;
183182
184183 try {
185- $ metadata = $ this ->metadataFactory -> metadata ($ object ::class);
184+ $ metadata = $ this ->metadata ($ object ::class);
186185
187186 foreach ($ metadata ->preExtractCallbacks as $ callback ) {
188187 $ callback ->invoke ($ object );
@@ -197,10 +196,6 @@ public function extract(object $object): array
197196 $ normalizer = $ propertyMetadata ->normalizer ;
198197
199198 if ($ normalizer ) {
200- if ($ normalizer instanceof HydratorAwareNormalizer) {
201- $ normalizer ->setHydrator ($ this );
202- }
203-
204199 try {
205200 /** @psalm-suppress MixedAssignment */
206201 $ value = $ normalizer ->normalize ($ value );
@@ -261,6 +256,32 @@ private function promotedConstructorParametersWithDefaultValue(ClassMetadata $me
261256 return $ result ;
262257 }
263258
259+ /**
260+ * @param class-string<T> $class
261+ *
262+ * @return ClassMetadata<T>
263+ *
264+ * @template T of object
265+ */
266+ private function metadata (string $ class ): ClassMetadata
267+ {
268+ if (isset ($ this ->classMetadata [$ class ])) {
269+ return $ this ->classMetadata [$ class ];
270+ }
271+
272+ $ this ->classMetadata [$ class ] = $ metadata = $ this ->metadataFactory ->metadata ($ class );
273+
274+ foreach ($ metadata ->properties as $ property ) {
275+ if (!($ property ->normalizer instanceof HydratorAwareNormalizer)) {
276+ continue ;
277+ }
278+
279+ $ property ->normalizer ->setHydrator ($ this );
280+ }
281+
282+ return $ metadata ;
283+ }
284+
264285 /** @param iterable<Guesser> $guessers */
265286 public static function create (
266287 iterable $ guessers = [],
0 commit comments