Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit940e9ca

Browse files
committed
Fix denormalizing empty string into object|null parameter
1 parenteee7e8f commit940e9ca

File tree

6 files changed

+159
-10
lines changed

6 files changed

+159
-10
lines changed

‎src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php‎

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -290,8 +290,6 @@ abstract protected function extractAttributes(object $object, string $format = n
290290

291291
/**
292292
* Gets the attribute value.
293-
*
294-
* @return mixed
295293
*/
296294
abstractprotectedfunctiongetAttributeValue(object$object,string$attribute,string$format =null,array$context = []);
297295

@@ -305,9 +303,6 @@ public function supportsDenormalization(mixed $data, string $type, string $forma
305303
returnclass_exists($type) || (interface_exists($type,false) &&null !==$this->classDiscriminatorResolver?->getMappingForClass($type));
306304
}
307305

308-
/**
309-
* @return mixed
310-
*/
311306
publicfunctiondenormalize(mixed$data,string$type,string$format =null,array$context = [])
312307
{
313308
if (!isset($context['cache_key'])) {
@@ -434,11 +429,16 @@ private function validateAndDenormalize(array $types, string $currentClass, stri
434429
$isUnionType =\count($types) >1;
435430
$extraAttributesException =null;
436431
$missingConstructorArgumentsException =null;
432+
$hasNonObjectType =false;
433+
$isUnionTypeOrNullable =$isUnionType;
434+
437435
foreach ($typesas$type) {
438436
if (null ===$data &&$type->isNullable()) {
439437
returnnull;
440438
}
441439

440+
$isUnionTypeOrNullable =$isUnionTypeOrNullable ?:$type->isNullable();
441+
$hasNonObjectType =$hasNonObjectType ?: Type::BUILTIN_TYPE_OBJECT !==$type->getBuiltinType();
442442
$collectionValueType =$type->isCollection() ?$type->getCollectionValueTypes()[0] ??null :null;
443443

444444
// Fix a collection that contains the only one element
@@ -456,9 +456,10 @@ private function validateAndDenormalize(array $types, string $currentClass, stri
456456
// In XML and CSV all basic datatypes are represented as strings, it is e.g. not possible to determine,
457457
// if a value is meant to be a string, float, int or a boolean value from the serialized representation.
458458
// That's why we have to transform the values, if one of these non-string basic datatypes is expected.
459+
$builtinType =$type->getBuiltinType();
459460
if (\is_string($data) && (XmlEncoder::FORMAT ===$format || CsvEncoder::FORMAT ===$format)) {
460461
if ('' ===$data) {
461-
if (Type::BUILTIN_TYPE_ARRAY ===$builtinType =$type->getBuiltinType()) {
462+
if (Type::BUILTIN_TYPE_ARRAY ===$builtinType) {
462463
return [];
463464
}
464465

@@ -467,7 +468,7 @@ private function validateAndDenormalize(array $types, string $currentClass, stri
467468
}
468469
}
469470

470-
switch ($builtinType ??$type->getBuiltinType()) {
471+
switch ($builtinType) {
471472
case Type::BUILTIN_TYPE_BOOL:
472473
// according to https://www.w3.org/TR/xmlschema-2/#boolean, valid representations are "false", "true", "0" and "1"
473474
if ('false' ===$data ||'0' ===$data) {
@@ -564,24 +565,28 @@ private function validateAndDenormalize(array $types, string $currentClass, stri
564565
return$data;
565566
}
566567
}catch (NotNormalizableValueException|InvalidArgumentException$e) {
567-
if (!$isUnionType) {
568+
if (!$isUnionTypeOrNullable) {
568569
throw$e;
569570
}
570571
}catch (ExtraAttributesException$e) {
571-
if (!$isUnionType) {
572+
if (!$isUnionTypeOrNullable) {
572573
throw$e;
573574
}
574575

575576
$extraAttributesException ??=$e;
576577
}catch (MissingConstructorArgumentsException$e) {
577-
if (!$isUnionType) {
578+
if (!$isUnionTypeOrNullable) {
578579
throw$e;
579580
}
580581

581582
$missingConstructorArgumentsException ??=$e;
582583
}
583584
}
584585

586+
if ('' ===$data &&$isUnionTypeOrNullable && !$hasNonObjectType && (XmlEncoder::FORMAT ===$format || CsvEncoder::FORMAT ===$format)) {
587+
returnnull;
588+
}
589+
585590
if ($extraAttributesException) {
586591
throw$extraAttributesException;
587592
}
@@ -590,6 +595,10 @@ private function validateAndDenormalize(array $types, string $currentClass, stri
590595
throw$missingConstructorArgumentsException;
591596
}
592597

598+
if (!$isUnionType &&isset($e)) {
599+
throw$e;
600+
}
601+
593602
if ($context[self::DISABLE_TYPE_ENFORCEMENT] ??$this->defaultContext[self::DISABLE_TYPE_ENFORCEMENT] ??false) {
594603
return$data;
595604
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespaceSymfony\Component\Serializer\Tests\Fixtures;
13+
14+
/**
15+
* @author Jeroen <github.com/Jeroeny>
16+
*/
17+
class DummyWithNotNormalizable
18+
{
19+
publicfunction__construct(publicNotNormalizableDummy|null$value)
20+
{
21+
}
22+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespaceSymfony\Component\Serializer\Tests\Fixtures;
13+
14+
/**
15+
* @author Jeroen <github.com/Jeroeny>
16+
*/
17+
class DummyWithObjectOrBool
18+
{
19+
publicfunction__construct(publicPhp80WithPromotedTypedConstructor|bool$value)
20+
{
21+
}
22+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespaceSymfony\Component\Serializer\Tests\Fixtures;
13+
14+
/**
15+
* @author Jeroen <github.com/Jeroeny>
16+
*/
17+
class DummyWithObjectOrNull
18+
{
19+
publicfunction__construct(publicPhp80WithPromotedTypedConstructor|null$value)
20+
{
21+
}
22+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespaceSymfony\Component\Serializer\Tests\Fixtures;
13+
14+
useSymfony\Component\Serializer\Exception\NotNormalizableValueException;
15+
useSymfony\Component\Serializer\Normalizer\DenormalizableInterface;
16+
useSymfony\Component\Serializer\Normalizer\DenormalizerInterface;
17+
18+
/**
19+
* @author Jeroen <github.com/Jeroeny>
20+
*/
21+
class NotNormalizableDummyimplements DenormalizableInterface
22+
{
23+
publicfunction__construct()
24+
{
25+
}
26+
27+
publicfunctiondenormalize(DenormalizerInterface$denormalizer,float|int|bool|array|string$data,string$format =null,array$context = [])
28+
{
29+
thrownewNotNormalizableValueException();
30+
}
31+
}

‎src/Symfony/Component/Serializer/Tests/SerializerTest.php‎

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@
1616
useSymfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
1717
useSymfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
1818
useSymfony\Component\PropertyInfo\PropertyInfoExtractor;
19+
useSymfony\Component\Serializer\Encoder\CsvEncoder;
1920
useSymfony\Component\Serializer\Encoder\JsonEncoder;
2021
useSymfony\Component\Serializer\Exception\ExtraAttributesException;
2122
useSymfony\Component\Serializer\Exception\InvalidArgumentException;
2223
useSymfony\Component\Serializer\Exception\LogicException;
24+
useSymfony\Component\Serializer\Exception\MissingConstructorArgumentsException;
2325
useSymfony\Component\Serializer\Exception\NotNormalizableValueException;
2426
useSymfony\Component\Serializer\Exception\PartialDenormalizationException;
2527
useSymfony\Component\Serializer\Exception\UnexpectedValueException;
@@ -57,6 +59,9 @@
5759
useSymfony\Component\Serializer\Tests\Fixtures\DummyMessageNumberTwo;
5860
useSymfony\Component\Serializer\Tests\Fixtures\DummyObjectWithEnumConstructor;
5961
useSymfony\Component\Serializer\Tests\Fixtures\DummyObjectWithEnumProperty;
62+
useSymfony\Component\Serializer\Tests\Fixtures\DummyWithNotNormalizable;
63+
useSymfony\Component\Serializer\Tests\Fixtures\DummyWithObjectOrBool;
64+
useSymfony\Component\Serializer\Tests\Fixtures\DummyWithObjectOrNull;
6065
useSymfony\Component\Serializer\Tests\Fixtures\FalseBuiltInDummy;
6166
useSymfony\Component\Serializer\Tests\Fixtures\FooImplementationDummy;
6267
useSymfony\Component\Serializer\Tests\Fixtures\FooInterfaceDummyDenormalizer;
@@ -842,6 +847,44 @@ public function testTrueBuiltInTypes()
842847
$this->assertEquals(newTrueBuiltInDummy(),$actual);
843848
}
844849

850+
publicfunctiontestDeserializeUntypedFormat()
851+
{
852+
$serializer =newSerializer([newObjectNormalizer(propertyTypeExtractor:newPropertyInfoExtractor([], [newPhpDocExtractor(),newReflectionExtractor()]))], ['csv' =>newCsvEncoder()]);
853+
$actual =$serializer->deserialize('value'.\PHP_EOL.',', DummyWithObjectOrNull::class,'csv', [CsvEncoder::AS_COLLECTION_KEY =>false]);
854+
855+
$this->assertEquals(newDummyWithObjectOrNull(null),$actual);
856+
}
857+
858+
publicfunctiontestDenormalizeUntypedFormat()
859+
{
860+
$serializer =newSerializer([newObjectNormalizer(propertyTypeExtractor:newPropertyInfoExtractor([], [newPhpDocExtractor(),newReflectionExtractor()]))]);
861+
$actual =$serializer->denormalize(['value' =>''], DummyWithObjectOrNull::class,'xml');
862+
863+
$this->assertEquals(newDummyWithObjectOrNull(null),$actual);
864+
}
865+
866+
publicfunctiontestDenormalizeUntypedFormatNotNormalizable()
867+
{
868+
$this->expectException(NotNormalizableValueException::class);
869+
$serializer =newSerializer([newCustomNormalizer(),newObjectNormalizer(propertyTypeExtractor:newPropertyInfoExtractor([], [newPhpDocExtractor(),newReflectionExtractor()]))]);
870+
$serializer->denormalize(['value' =>'test'], DummyWithNotNormalizable::class,'xml');
871+
}
872+
873+
publicfunctiontestDenormalizeUntypedFormatMissingArg()
874+
{
875+
$this->expectException(MissingConstructorArgumentsException::class);
876+
$serializer =newSerializer([newObjectNormalizer(propertyTypeExtractor:newPropertyInfoExtractor([], [newPhpDocExtractor(),newReflectionExtractor()]))]);
877+
$serializer->denormalize(['value' =>'invalid'], DummyWithObjectOrNull::class,'xml');
878+
}
879+
880+
publicfunctiontestDenormalizeUntypedFormatScalar()
881+
{
882+
$serializer =newSerializer([newObjectNormalizer(propertyTypeExtractor:newPropertyInfoExtractor([], [newPhpDocExtractor(),newReflectionExtractor()]))]);
883+
$actual =$serializer->denormalize(['value' =>'false'], DummyWithObjectOrBool::class,'xml');
884+
885+
$this->assertEquals(newDummyWithObjectOrBool(false),$actual);
886+
}
887+
845888
privatefunctionserializerWithClassDiscriminator()
846889
{
847890
$classMetadataFactory =newClassMetadataFactory(newAttributeLoader());

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp