From 59699189f2136f6fdd9b485ad2d1f1b28c12adf6 Mon Sep 17 00:00:00 2001 From: Maximilian Zumbansen Date: Wed, 26 Jun 2024 14:46:59 +0200 Subject: [PATCH] [Serializer] [ObjectNormalizer] Use bool filter when FILTER_BOOL is set --- Normalizer/AbstractObjectNormalizer.php | 8 +++++ .../AbstractObjectNormalizerTest.php | 34 +++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/Normalizer/AbstractObjectNormalizer.php b/Normalizer/AbstractObjectNormalizer.php index 2d067135..ab956845 100644 --- a/Normalizer/AbstractObjectNormalizer.php +++ b/Normalizer/AbstractObjectNormalizer.php @@ -566,6 +566,10 @@ private function validateAndDenormalizeLegacy(array $types, string $currentClass return (float) $data; } + if (LegacyType::BUILTIN_TYPE_BOOL === $builtinType && \is_string($data) && ($context[self::FILTER_BOOL] ?? false)) { + return filter_var($data, \FILTER_VALIDATE_BOOL, \FILTER_NULL_ON_FAILURE); + } + if ((LegacyType::BUILTIN_TYPE_FALSE === $builtinType && false === $data) || (LegacyType::BUILTIN_TYPE_TRUE === $builtinType && true === $data)) { return $data; } @@ -787,6 +791,10 @@ private function validateAndDenormalize(Type $type, string $currentClass, string return (float) $data; } + if (TypeIdentifier::BOOL === $typeIdentifier && \is_string($data) && ($context[self::FILTER_BOOL] ?? false)) { + return filter_var($data, \FILTER_VALIDATE_BOOL, \FILTER_NULL_ON_FAILURE); + } + $dataMatchesExpectedType = match ($typeIdentifier) { TypeIdentifier::ARRAY => \is_array($data), TypeIdentifier::BOOL => \is_bool($data), diff --git a/Tests/Normalizer/AbstractObjectNormalizerTest.php b/Tests/Normalizer/AbstractObjectNormalizerTest.php index c5c1f6f0..90e6be95 100644 --- a/Tests/Normalizer/AbstractObjectNormalizerTest.php +++ b/Tests/Normalizer/AbstractObjectNormalizerTest.php @@ -1195,6 +1195,34 @@ public function provideBooleanTypesData() [['foo' => false], TruePropertyDummy::class], ]; } + + /** + * @dataProvider provideDenormalizeWithFilterBoolData + */ + public function testDenormalizeBooleanTypeWithFilterBool(array $data, ?bool $expectedFoo) + { + $normalizer = new AbstractObjectNormalizerWithMetadataAndPropertyTypeExtractors(); + + $dummy = $normalizer->denormalize($data, BoolPropertyDummy::class, null, [AbstractNormalizer::FILTER_BOOL => true]); + + $this->assertSame($expectedFoo, $dummy->foo); + } + + public function provideDenormalizeWithFilterBoolData(): array + { + return [ + [['foo' => 'true'], true], + [['foo' => '1'], true], + [['foo' => 'yes'], true], + [['foo' => 'false'], false], + [['foo' => '0'], false], + [['foo' => 'no'], false], + [['foo' => ''], false], + [['foo' => null], null], + [['foo' => 'null'], null], + [['foo' => 'something'], null], + ]; + } } class AbstractObjectNormalizerDummy extends AbstractObjectNormalizer @@ -1480,6 +1508,12 @@ class TruePropertyDummy public $foo; } +class BoolPropertyDummy +{ + /** @var null|bool */ + public $foo; +} + class SerializerCollectionDummy implements SerializerInterface, DenormalizerInterface { private array $normalizers;