Skip to content

Commit e1e8e32

Browse files
Christian Kolbnicolas-grekas
authored andcommitted
[Serializer] Add flag to require all properties to be listed in the input
1 parent e0b00fa commit e1e8e32

File tree

5 files changed

+30
-1
lines changed

5 files changed

+30
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ CHANGELOG
44
6.3
55
---
66

7+
* Add `AbstractNormalizer::REQUIRE_ALL_PROPERTIES` context flag to require all properties to be listed in the input instead of falling back to null for nullable ones
78
* Add `XmlEncoder::SAVE_OPTIONS` context option
89
* Add `BackedEnumNormalizer::ALLOW_INVALID_VALUES` context option
910
* Add `UnsupportedFormatException` which is thrown when there is no decoder for a given format

Context/Normalizer/AbstractNormalizerContextBuilder.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,4 +164,13 @@ public function withIgnoredAttributes(?array $ignoredAttributes): static
164164
{
165165
return $this->with(AbstractNormalizer::IGNORED_ATTRIBUTES, $ignoredAttributes);
166166
}
167+
168+
/**
169+
* Configures requiring all properties to be listed in the input instead
170+
* of falling back to null for nullable ones.
171+
*/
172+
public function withRequireAllProperties(?bool $requireAllProperties = true): static
173+
{
174+
return $this->with(AbstractNormalizer::REQUIRE_ALL_PROPERTIES, $requireAllProperties);
175+
}
167176
}

Normalizer/AbstractNormalizer.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,12 @@ abstract class AbstractNormalizer implements NormalizerInterface, DenormalizerIn
112112
*/
113113
public const IGNORED_ATTRIBUTES = 'ignored_attributes';
114114

115+
/**
116+
* Require all properties to be listed in the input instead of falling
117+
* back to null for nullable ones.
118+
*/
119+
public const REQUIRE_ALL_PROPERTIES = 'require_all_properties';
120+
115121
/**
116122
* @internal
117123
*/
@@ -383,7 +389,7 @@ protected function instantiateObject(array &$data, string $class, array &$contex
383389
$params[] = $this->defaultContext[self::DEFAULT_CONSTRUCTOR_ARGUMENTS][$class][$key];
384390
} elseif ($constructorParameter->isDefaultValueAvailable()) {
385391
$params[] = $constructorParameter->getDefaultValue();
386-
} elseif ($constructorParameter->hasType() && $constructorParameter->getType()->allowsNull()) {
392+
} elseif (!($context[self::REQUIRE_ALL_PROPERTIES] ?? $this->defaultContext[self::REQUIRE_ALL_PROPERTIES] ?? false) && $constructorParameter->hasType() && $constructorParameter->getType()->allowsNull()) {
387393
$params[] = null;
388394
} else {
389395
if (!isset($context['not_normalizable_value_exceptions'])) {

Tests/Context/Normalizer/AbstractNormalizerContextBuilderTest.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public function testWithers(array $values)
4545
->withCallbacks($values[AbstractNormalizer::CALLBACKS])
4646
->withCircularReferenceHandler($values[AbstractNormalizer::CIRCULAR_REFERENCE_HANDLER])
4747
->withIgnoredAttributes($values[AbstractNormalizer::IGNORED_ATTRIBUTES])
48+
->withRequireAllProperties($values[AbstractNormalizer::REQUIRE_ALL_PROPERTIES])
4849
->toArray();
4950

5051
$this->assertEquals($values, $context);
@@ -65,6 +66,7 @@ public static function withersDataProvider(): iterable
6566
AbstractNormalizer::CALLBACKS => [static function (): void {}],
6667
AbstractNormalizer::CIRCULAR_REFERENCE_HANDLER => static function (): void {},
6768
AbstractNormalizer::IGNORED_ATTRIBUTES => ['attribute3'],
69+
AbstractNormalizer::REQUIRE_ALL_PROPERTIES => true,
6870
]];
6971

7072
yield 'With null values' => [[
@@ -77,6 +79,7 @@ public static function withersDataProvider(): iterable
7779
AbstractNormalizer::CALLBACKS => null,
7880
AbstractNormalizer::CIRCULAR_REFERENCE_HANDLER => null,
7981
AbstractNormalizer::IGNORED_ATTRIBUTES => null,
82+
AbstractNormalizer::REQUIRE_ALL_PROPERTIES => null,
8083
]];
8184
}
8285

Tests/Normalizer/AbstractNormalizerTest.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use PHPUnit\Framework\TestCase;
1616
use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
1717
use Symfony\Component\Serializer\Encoder\JsonEncoder;
18+
use Symfony\Component\Serializer\Exception\MissingConstructorArgumentsException;
1819
use Symfony\Component\Serializer\Mapping\AttributeMetadata;
1920
use Symfony\Component\Serializer\Mapping\ClassMetadata;
2021
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
@@ -166,6 +167,15 @@ public function testObjectWithNullableNonOptionalConstructorArgumentWithoutInput
166167
$this->assertNull($dummy->getFoo());
167168
}
168169

170+
public function testObjectWithNullableNonOptionalConstructorArgumentWithoutInputAndRequireAllProperties()
171+
{
172+
$normalizer = new ObjectNormalizer();
173+
174+
$this->expectException(MissingConstructorArgumentsException::class);
175+
176+
$normalizer->denormalize([], NullableConstructorArgumentDummy::class, null, [AbstractNormalizer::REQUIRE_ALL_PROPERTIES => true]);
177+
}
178+
169179
/**
170180
* @dataProvider getNormalizer
171181
*/

0 commit comments

Comments
 (0)