Skip to content

Commit 33b1658

Browse files
committed
fix(serializer): disable_type_enforcement with null values (#5593)
fixes #5584
1 parent 502234c commit 33b1658

File tree

3 files changed

+67
-1
lines changed

3 files changed

+67
-1
lines changed

src/Serializer/AbstractItemNormalizer.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -753,7 +753,7 @@ private function createAndValidateAttributeValue(string $attribute, mixed $value
753753
return $value;
754754
}
755755

756-
if (null === $value && $type->isNullable()) {
756+
if (null === $value && ($type->isNullable() || ($context[static::DISABLE_TYPE_ENFORCEMENT] ?? false))) {
757757
return $value;
758758
}
759759

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <[email protected]>
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+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue5584;
15+
16+
use ApiPlatform\Metadata\ApiResource;
17+
use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer;
18+
19+
#[ApiResource(denormalizationContext: [AbstractObjectNormalizer::DISABLE_TYPE_ENFORCEMENT => true])]
20+
final class DtoWithNullValue
21+
{
22+
public \stdClass $dummy;
23+
}

tests/Serializer/AbstractItemNormalizerTest.php

+43
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use ApiPlatform\Metadata\Property\PropertyNameCollection;
2222
use ApiPlatform\Serializer\AbstractItemNormalizer;
2323
use ApiPlatform\Symfony\Security\ResourceAccessCheckerInterface;
24+
use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue5584\DtoWithNullValue;
2425
use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy;
2526
use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyTableInheritance;
2627
use ApiPlatform\Tests\Fixtures\TestBundle\Entity\DummyTableInheritanceChild;
@@ -1347,6 +1348,48 @@ public function testDenormalizePopulatingNonCloneableObject(): void
13471348
$this->assertSame($dummy, $actual);
13481349
$propertyAccessorProphecy->setValue($actual, 'name', 'bar')->shouldHaveBeenCalled();
13491350
}
1351+
1352+
public function testDenormalizeObjectWithNullDisabledTypeEnforcement(): void
1353+
{
1354+
$data = [
1355+
'dummy' => null,
1356+
];
1357+
1358+
$propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class);
1359+
$propertyNameCollectionFactoryProphecy->create(DtoWithNullValue::class, [])->willReturn(new PropertyNameCollection(['dummy']));
1360+
1361+
$propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class);
1362+
$propertyMetadataFactoryProphecy->create(DtoWithNullValue::class, 'dummy', [])->willReturn((new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_OBJECT, nullable: true)])->withDescription('')->withReadable(true)->withWritable(true));
1363+
1364+
$iriConverterProphecy = $this->prophesize(IriConverterInterface::class);
1365+
$propertyAccessorProphecy = $this->prophesize(PropertyAccessorInterface::class);
1366+
$resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class);
1367+
$resourceClassResolverProphecy->getResourceClass(null, DtoWithNullValue::class)->willReturn(DtoWithNullValue::class);
1368+
$resourceClassResolverProphecy->isResourceClass(DtoWithNullValue::class)->willReturn(true);
1369+
1370+
$serializerProphecy = $this->prophesize(SerializerInterface::class);
1371+
$serializerProphecy->willImplement(NormalizerInterface::class);
1372+
1373+
$normalizer = $this->getMockForAbstractClass(AbstractItemNormalizer::class, [
1374+
$propertyNameCollectionFactoryProphecy->reveal(),
1375+
$propertyMetadataFactoryProphecy->reveal(),
1376+
$iriConverterProphecy->reveal(),
1377+
$resourceClassResolverProphecy->reveal(),
1378+
$propertyAccessorProphecy->reveal(),
1379+
null,
1380+
null,
1381+
[],
1382+
null,
1383+
null,
1384+
]);
1385+
$normalizer->setSerializer($serializerProphecy->reveal());
1386+
1387+
$context = [AbstractItemNormalizer::DISABLE_TYPE_ENFORCEMENT => true];
1388+
$actual = $normalizer->denormalize($data, DtoWithNullValue::class, null, $context);
1389+
1390+
$this->assertInstanceOf(DtoWithNullValue::class, $actual);
1391+
$this->assertEquals(new DtoWithNullValue(), $actual);
1392+
}
13501393
}
13511394

13521395
class ObjectWithBasicProperties

0 commit comments

Comments
 (0)