diff --git a/src/Symfony/Component/Serializer/CHANGELOG.md b/src/Symfony/Component/Serializer/CHANGELOG.md index 3f16b2ba42ac3..791a6c759fd44 100644 --- a/src/Symfony/Component/Serializer/CHANGELOG.md +++ b/src/Symfony/Component/Serializer/CHANGELOG.md @@ -10,6 +10,7 @@ CHANGELOG * Deprecate `ContextAwareDenormalizerInterface`, use `DenormalizerInterface` instead * Deprecate `ContextAwareEncoderInterface`, use `EncoderInterface` instead * Deprecate `ContextAwareDecoderInterface`, use `DecoderInterface` instead + * Add the ability to only check the first element in `ArrayDenormalizer` 6.0 --- diff --git a/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php b/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php index a212704b7c596..bd092792b4319 100644 --- a/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php @@ -26,6 +26,10 @@ class ArrayDenormalizer implements ContextAwareDenormalizerInterface, Denormaliz { use DenormalizerAwareTrait; + public function __construct(private bool $checkFirstElement = false) + { + } + /** * {@inheritdoc} * @@ -69,8 +73,16 @@ public function supportsDenormalization(mixed $data, string $type, string $forma throw new BadMethodCallException(sprintf('The nested denormalizer needs to be set to allow "%s()" to be used.', __METHOD__)); } - return str_ends_with($type, '[]') - && $this->denormalizer->supportsDenormalization($data, substr($type, 0, -2), $format, $context); + if (!str_ends_with($type, '[]')) { + return false; + } + + if ($this->checkFirstElement) { + $data = \is_array($data) ? $data : []; + $data = 0 === \count($data) ? null : reset($data); + } + + return $this->denormalizer->supportsDenormalization($data, substr($type, 0, -2), $format, $context); } /** diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/ArrayDenormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/ArrayDenormalizerTest.php index 9fd513ab597ae..72fb94734d9e0 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/ArrayDenormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/ArrayDenormalizerTest.php @@ -111,6 +111,89 @@ public function testSupportsNoArray() ) ); } + + public function testSupportsOtherDatatype() + { + $this->assertFalse( + $this->denormalizer->supportsDenormalization( + '83fd8e7c-61d4-4318-af88-fb34bd05e31f', + __NAMESPACE__.'\Uuid' + ) + ); + + $denormalizer2 = new ArrayDenormalizer(true); + $denormalizer2->setDenormalizer($this->serializer); + + $this->assertFalse( + $denormalizer2->supportsDenormalization( + '83fd8e7c-61d4-4318-af88-fb34bd05e31f', + __NAMESPACE__.'\Uuid' + ) + ); + } + + public function testSupportsValidFirstArrayElement() + { + $denormalizer = new ArrayDenormalizer(true); + $denormalizer->setDenormalizer($this->serializer); + + $this->serializer->expects($this->once()) + ->method('supportsDenormalization') + ->with(['foo' => 'one', 'bar' => 'two'], ArrayDummy::class, 'json', []) + ->willReturn(true); + + $this->assertTrue( + $denormalizer->supportsDenormalization( + [ + ['foo' => 'one', 'bar' => 'two'], + ['foo' => 'three', 'bar' => 'four'], + ], + __NAMESPACE__.'\ArrayDummy[]', + 'json' + ) + ); + } + + public function testSupportsInValidFirstArrayElement() + { + $denormalizer = new ArrayDenormalizer(true); + $denormalizer->setDenormalizer($this->serializer); + + $this->serializer->expects($this->once()) + ->method('supportsDenormalization') + ->with(['foo' => 'one', 'bar' => 'two'], ArrayDummy::class, 'json', []) + ->willReturn(false); + + $this->assertFalse( + $denormalizer->supportsDenormalization( + [ + ['foo' => 'one', 'bar' => 'two'], + ['foo' => 'three', 'bar' => 'four'], + ], + __NAMESPACE__.'\ArrayDummy[]', + 'json' + ) + ); + } + + public function testSupportsNoFirstArrayElement() + { + $denormalizer = new ArrayDenormalizer(true); + $denormalizer->setDenormalizer($this->serializer); + + $this->serializer->expects($this->once()) + ->method('supportsDenormalization') + ->with($this->isNull(), ArrayDummy::class, 'json', []) + ->willReturn(true); + + $this->assertTrue( + $denormalizer->supportsDenormalization( + [], + __NAMESPACE__.'\ArrayDummy[]', + 'json' + ) + ); + } } class ArrayDummy