From 6984dcee27b3f35fb8bd3ade595f24b4555d0454 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sun, 19 Mar 2023 19:19:19 +0100 Subject: [PATCH] [Serializer] Allow filtering "object" when using "getSupportedTypes()" --- .../Normalizer/ArrayDenormalizer.php | 7 +----- .../Normalizer/DenormalizerInterface.php | 14 ++++------- .../Normalizer/GetSetMethodNormalizer.php | 2 +- .../Normalizer/NormalizerInterface.php | 14 ++++------- .../Normalizer/ObjectNormalizer.php | 2 +- .../Normalizer/PropertyNormalizer.php | 2 +- .../Component/Serializer/Serializer.php | 25 +++++++++++++------ .../Tests/Fixtures/Annotations/GroupDummy.php | 2 +- .../DummyObjectWithEnumConstructor.php | 11 ++++++-- .../Serializer/Tests/Fixtures/Php74Full.php | 1 - .../Serializer/Tests/SerializerTest.php | 3 --- 11 files changed, 42 insertions(+), 41 deletions(-) diff --git a/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php b/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php index 8b36935081f30..b37e9eace0041 100644 --- a/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php @@ -38,12 +38,7 @@ public function setDenormalizer(DenormalizerInterface $denormalizer): void public function getSupportedTypes(?string $format): array { - // @deprecated remove condition in 7.0 - if (!method_exists($this->denormalizer, 'getSupportedTypes')) { - return ['*' => $this->denormalizer instanceof CacheableSupportsMethodInterface && $this->denormalizer->hasCacheableSupportsMethod()]; - } - - return $this->denormalizer->getSupportedTypes($format); + return ['object' => null, '*' => false]; } /** diff --git a/src/Symfony/Component/Serializer/Normalizer/DenormalizerInterface.php b/src/Symfony/Component/Serializer/Normalizer/DenormalizerInterface.php index 1d83b2da1166d..4edb70096daaa 100644 --- a/src/Symfony/Component/Serializer/Normalizer/DenormalizerInterface.php +++ b/src/Symfony/Component/Serializer/Normalizer/DenormalizerInterface.php @@ -51,11 +51,6 @@ public function denormalize(mixed $data, string $type, string $format = null, ar /** * Checks whether the given class is supported for denormalization by this normalizer. * - * Since Symfony 6.3, this method will only be called if the type is - * included in the supported types returned by getSupportedTypes(). - * - * @see getSupportedTypes() - * * @param mixed $data Data to denormalize from * @param string $type The class to which the data should be denormalized * @param string|null $format The format being deserialized from @@ -72,12 +67,13 @@ public function supportsDenormalization(mixed $data, string $type, string $forma * returned as keys, and each type should be mapped to a boolean indicating * if the result of supportsDenormalization() can be cached or not * (a result cannot be cached when it depends on the context or on the data.) + * A null value means that the denormalizer does not support the corresponding + * type. * - * The special type '*' can be used to indicate that the denormalizer might - * support any types. A null value means that the denormalizer does not support - * the corresponding type. + * Use type "object" to match any classes or interfaces, + * and type "*" to match any types. * - * @return array + * @return array */ /* public function getSupportedTypes(?string $format): array; */ } diff --git a/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php index 2719c8b52c16e..403bb2a45f621 100644 --- a/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php @@ -38,7 +38,7 @@ class GetSetMethodNormalizer extends AbstractObjectNormalizer public function getSupportedTypes(?string $format): array { - return ['*' => __CLASS__ === static::class || $this->hasCacheableSupportsMethod()]; + return ['object' => __CLASS__ === static::class || $this->hasCacheableSupportsMethod()]; } /** diff --git a/src/Symfony/Component/Serializer/Normalizer/NormalizerInterface.php b/src/Symfony/Component/Serializer/Normalizer/NormalizerInterface.php index d6d0707ff5ec8..40779de316d7c 100644 --- a/src/Symfony/Component/Serializer/Normalizer/NormalizerInterface.php +++ b/src/Symfony/Component/Serializer/Normalizer/NormalizerInterface.php @@ -43,11 +43,6 @@ public function normalize(mixed $object, string $format = null, array $context = /** * Checks whether the given class is supported for normalization by this normalizer. * - * Since Symfony 6.3, this method will only be called if the $data type is - * included in the supported types returned by getSupportedTypes(). - * - * @see getSupportedTypes() - * * @param mixed $data Data to normalize * @param string|null $format The format being (de-)serialized from or into * @param array $context Context options for the normalizer @@ -63,12 +58,13 @@ public function supportsNormalization(mixed $data, string $format = null /* , ar * returned as keys, and each type should be mapped to a boolean indicating * if the result of supportsNormalization() can be cached or not * (a result cannot be cached when it depends on the context or on the data.) + * A null value means that the normalizer does not support the corresponding + * type. * - * The special type '*' can be used to indicate that the normalizer might - * support any types. A null value means that the normalizer does not support - * the corresponding type. + * Use type "object" to match any classes or interfaces, + * and type "*" to match any types. * - * @return array + * @return array */ /* public function getSupportedTypes(?string $format): array; */ } diff --git a/src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php index 140e89c6a13b1..dce4434641346 100644 --- a/src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php @@ -49,7 +49,7 @@ public function __construct(ClassMetadataFactoryInterface $classMetadataFactory public function getSupportedTypes(?string $format): array { - return ['*' => __CLASS__ === static::class || $this->hasCacheableSupportsMethod()]; + return ['object' => __CLASS__ === static::class || $this->hasCacheableSupportsMethod()]; } /** diff --git a/src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php index 645ba74290249..56e5ebf740760 100644 --- a/src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php @@ -56,7 +56,7 @@ public function __construct(ClassMetadataFactoryInterface $classMetadataFactory public function getSupportedTypes(?string $format): array { - return ['*' => __CLASS__ === static::class || $this->hasCacheableSupportsMethod()]; + return ['object' => __CLASS__ === static::class || $this->hasCacheableSupportsMethod()]; } /** diff --git a/src/Symfony/Component/Serializer/Serializer.php b/src/Symfony/Component/Serializer/Serializer.php index 5eb0c5b6b2e2e..ea219f40351bb 100644 --- a/src/Symfony/Component/Serializer/Serializer.php +++ b/src/Symfony/Component/Serializer/Serializer.php @@ -251,7 +251,13 @@ public function supportsDenormalization(mixed $data, string $type, string $forma */ private function getNormalizer(mixed $data, ?string $format, array $context): ?NormalizerInterface { - $type = \is_object($data) ? $data::class : 'native-'.\gettype($data); + if (\is_object($data)) { + $type = $data::class; + $genericType = 'object'; + } else { + $type = 'native-'.\gettype($data); + $genericType = '*'; + } if (!isset($this->normalizerCache[$format][$type])) { $this->normalizerCache[$format][$type] = []; @@ -277,12 +283,14 @@ private function getNormalizer(mixed $data, ?string $format, array $context): ?N $supportedTypes = $normalizer->getSupportedTypes($format); foreach ($supportedTypes as $supportedType => $isCacheable) { - if ('*' === $supportedType || $type !== $supportedType && !is_subclass_of($type, $supportedType, true)) { + if (\in_array($supportedType, ['*', 'object'], true) + || $type !== $supportedType && ('object' !== $genericType || !is_subclass_of($type, $supportedType)) + ) { continue; } if (null === $isCacheable) { - unset($supportedTypes['*']); + unset($supportedTypes['*'], $supportedTypes['object']); } elseif ($this->normalizerCache[$format][$type][$k] = $isCacheable && $normalizer->supportsNormalization($data, $format, $context)) { break 2; } @@ -290,7 +298,7 @@ private function getNormalizer(mixed $data, ?string $format, array $context): ?N break; } - if (null === $isCacheable = $supportedTypes['*'] ?? null) { + if (null === $isCacheable = $supportedTypes[\array_key_exists($genericType, $supportedTypes) ? $genericType : '*'] ?? null) { continue; } @@ -322,6 +330,7 @@ private function getDenormalizer(mixed $data, string $class, ?string $format, ar { if (!isset($this->denormalizerCache[$format][$class])) { $this->denormalizerCache[$format][$class] = []; + $genericType = class_exists($class) || interface_exists($class, false) ? 'object' : '*'; foreach ($this->normalizers as $k => $normalizer) { if (!$normalizer instanceof DenormalizerInterface) { @@ -344,12 +353,14 @@ private function getDenormalizer(mixed $data, string $class, ?string $format, ar $supportedTypes = $normalizer->getSupportedTypes($format); foreach ($supportedTypes as $supportedType => $isCacheable) { - if ('*' === $supportedType || $class !== $supportedType && !is_subclass_of($class, $supportedType, true)) { + if (\in_array($supportedType, ['*', 'object'], true) + || $class !== $supportedType && ('object' !== $genericType || !is_subclass_of($class, $supportedType)) + ) { continue; } if (null === $isCacheable) { - unset($supportedTypes['*']); + unset($supportedTypes['*'], $supportedTypes['object']); } elseif ($this->denormalizerCache[$format][$class][$k] = $isCacheable && $normalizer->supportsDenormalization(null, $class, $format, $context)) { break 2; } @@ -357,7 +368,7 @@ private function getDenormalizer(mixed $data, string $class, ?string $format, ar break; } - if (null === $isCacheable = $supportedTypes['*'] ?? null) { + if (null === $isCacheable = $supportedTypes[\array_key_exists($genericType, $supportedTypes) ? $genericType : '*'] ?? null) { continue; } diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/Annotations/GroupDummy.php b/src/Symfony/Component/Serializer/Tests/Fixtures/Annotations/GroupDummy.php index 1d502c60c5f86..36a63e6f816c8 100644 --- a/src/Symfony/Component/Serializer/Tests/Fixtures/Annotations/GroupDummy.php +++ b/src/Symfony/Component/Serializer/Tests/Fixtures/Annotations/GroupDummy.php @@ -12,8 +12,8 @@ namespace Symfony\Component\Serializer\Tests\Fixtures\Annotations; use Symfony\Component\Serializer\Annotation\Groups; -use Symfony\Component\Serializer\Tests\Fixtures\GroupDummyInterface; use Symfony\Component\Serializer\Tests\Fixtures\ChildOfGroupsAnnotationDummy; +use Symfony\Component\Serializer\Tests\Fixtures\GroupDummyInterface; /** * @author Kévin Dunglas diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/DummyObjectWithEnumConstructor.php b/src/Symfony/Component/Serializer/Tests/Fixtures/DummyObjectWithEnumConstructor.php index be5ea3cff0ece..022b57cd97efe 100644 --- a/src/Symfony/Component/Serializer/Tests/Fixtures/DummyObjectWithEnumConstructor.php +++ b/src/Symfony/Component/Serializer/Tests/Fixtures/DummyObjectWithEnumConstructor.php @@ -1,8 +1,15 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ -use Symfony\Component\Serializer\Tests\Fixtures\StringBackedEnumDummy; +namespace Symfony\Component\Serializer\Tests\Fixtures; class DummyObjectWithEnumConstructor { diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/Php74Full.php b/src/Symfony/Component/Serializer/Tests/Fixtures/Php74Full.php index 5aea0fa4af76f..0da6be20ff5b9 100644 --- a/src/Symfony/Component/Serializer/Tests/Fixtures/Php74Full.php +++ b/src/Symfony/Component/Serializer/Tests/Fixtures/Php74Full.php @@ -35,7 +35,6 @@ final class Php74Full public $anotherCollection; } - final class Php74FullWithConstructor { public function __construct($constructorArgument) diff --git a/src/Symfony/Component/Serializer/Tests/SerializerTest.php b/src/Symfony/Component/Serializer/Tests/SerializerTest.php index 331eaa25ea44d..8de4eefb758b1 100644 --- a/src/Symfony/Component/Serializer/Tests/SerializerTest.php +++ b/src/Symfony/Component/Serializer/Tests/SerializerTest.php @@ -17,8 +17,6 @@ use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor; use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor; use Symfony\Component\PropertyInfo\PropertyInfoExtractor; -use Symfony\Component\Serializer\Encoder\DecoderInterface; -use Symfony\Component\Serializer\Encoder\EncoderInterface; use Symfony\Component\Serializer\Encoder\JsonEncoder; use Symfony\Component\Serializer\Exception\ExtraAttributesException; use Symfony\Component\Serializer\Exception\InvalidArgumentException; @@ -49,7 +47,6 @@ use Symfony\Component\Serializer\Normalizer\UidNormalizer; use Symfony\Component\Serializer\Normalizer\UnwrappingDenormalizer; use Symfony\Component\Serializer\Serializer; -use Symfony\Component\Serializer\SerializerInterface; use Symfony\Component\Serializer\Tests\Fixtures\Annotations\AbstractDummy; use Symfony\Component\Serializer\Tests\Fixtures\Annotations\AbstractDummyFirstChild; use Symfony\Component\Serializer\Tests\Fixtures\Annotations\AbstractDummySecondChild; pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy