Skip to content

Commit

Permalink
bug #57541 [Serializer] [ObjectNormalizer] Use bool filter when FILTE…
Browse files Browse the repository at this point in the history
…R_BOOL is set (Maximilian Zumbansen)

This PR was squashed before being merged into the 7.1 branch.

Discussion
----------

[Serializer] [ObjectNormalizer] Use bool filter when FILTER_BOOL is set

| Q             | A
| ------------- | ---
| Branch?       | 7.1 <!-- see below -->
| Bug fix?      | yes
| New feature?  | no <!-- please update src/**/CHANGELOG.md files -->
| Deprecations? | no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files -->
| Issues        | Fix #57540 <!-- prefix each issue number with "Fix #", no need to create an issue if none exists, explain below instead -->
| License       | MIT

With 7.1 it is possible to map query booleans to php bool parameters (https://symfony.com/blog/new-in-symfony-7-1-misc-improvements-part-3#mapping-boolean-query-string-parameters). But as we found out, this only works when the DTO is initialized via `construct`. Otherwise the `FILTER_BOOL` flag will be ignored and e.g. "false" will be deserialized as `true`.

To fix this, I suggest to look for the `FILTER_BOOL` in the context and apply the filter, when the type is `bool` and the data is `string`.

Commits
-------

6e657e8e91 [Serializer] [ObjectNormalizer] Use bool filter when FILTER_BOOL is set
  • Loading branch information
nicolas-grekas committed Jun 28, 2024
2 parents a61c583 + 5969918 commit d207767
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 0 deletions.
8 changes: 8 additions & 0 deletions Normalizer/AbstractObjectNormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -797,6 +801,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),
Expand Down
34 changes: 34 additions & 0 deletions Tests/Normalizer/AbstractObjectNormalizerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1196,6 +1196,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
Expand Down Expand Up @@ -1481,6 +1509,12 @@ class TruePropertyDummy
public $foo;
}

class BoolPropertyDummy
{
/** @var null|bool */
public $foo;
}

class SerializerCollectionDummy implements SerializerInterface, DenormalizerInterface
{
private array $normalizers;
Expand Down

0 comments on commit d207767

Please sign in to comment.