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

Appearance settings

Commit 5ac8dc9

Browse filesBrowse files
committed
[Serializer] Throw NotNormalizableValueException when type is not known or not in body in discriminator map
1 parent 64cbfd2 commit 5ac8dc9
Copy full SHA for 5ac8dc9

File tree

3 files changed

+39
-11
lines changed
Filter options

3 files changed

+39
-11
lines changed

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php
+2-3Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
use Symfony\Component\Serializer\Exception\ExtraAttributesException;
2323
use Symfony\Component\Serializer\Exception\LogicException;
2424
use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
25-
use Symfony\Component\Serializer\Exception\RuntimeException;
2625
use Symfony\Component\Serializer\Mapping\AttributeMetadataInterface;
2726
use Symfony\Component\Serializer\Mapping\ClassDiscriminatorFromClassMetadata;
2827
use Symfony\Component\Serializer\Mapping\ClassDiscriminatorResolverInterface;
@@ -276,12 +275,12 @@ protected function instantiateObject(array &$data, string $class, array &$contex
276275
{
277276
if ($this->classDiscriminatorResolver && $mapping = $this->classDiscriminatorResolver->getMappingForClass($class)) {
278277
if (!isset($data[$mapping->getTypeProperty()])) {
279-
throw new RuntimeException(sprintf('Type property "%s" not found for the abstract object "%s".', $mapping->getTypeProperty(), $class));
278+
throw NotNormalizableValueException::createForUnexpectedDataType(sprintf('Type property "%s" not found for the abstract object "%s".', $mapping->getTypeProperty(), $class), null, ['string'], isset($context['deserialization_path']) ? $context['deserialization_path'].'.'.$mapping->getTypeProperty() : $mapping->getTypeProperty(), false);
280279
}
281280

282281
$type = $data[$mapping->getTypeProperty()];
283282
if (null === ($mappedClass = $mapping->getClassForType($type))) {
284-
throw new RuntimeException(sprintf('The type "%s" has no mapped class for the abstract object "%s".', $type, $class));
283+
throw NotNormalizableValueException::createForUnexpectedDataType(sprintf('The type "%s" is not a valid value.', $type), $type, ['string'], isset($context['deserialization_path']) ? $context['deserialization_path'].'.'.$mapping->getTypeProperty() : $mapping->getTypeProperty(), true);
285284
}
286285

287286
if ($mappedClass !== $class) {

‎src/Symfony/Component/Serializer/Tests/Fixtures/Php74Full.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Serializer/Tests/Fixtures/Php74Full.php
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ final class Php74Full
2828
/** @var Php74Full[] */
2929
public array $collection;
3030
public Php74FullWithConstructor $php74FullWithConstructor;
31+
public DummyMessageInterface $dummyMessage;
3132
}
3233

3334

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Serializer/Tests/SerializerTest.php
+36-8Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
use Symfony\Component\Serializer\Exception\LogicException;
2525
use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
2626
use Symfony\Component\Serializer\Exception\PartialDenormalizationException;
27-
use Symfony\Component\Serializer\Exception\RuntimeException;
2827
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
2928
use Symfony\Component\Serializer\Mapping\ClassDiscriminatorFromClassMetadata;
3029
use Symfony\Component\Serializer\Mapping\ClassDiscriminatorMapping;
@@ -484,16 +483,34 @@ public function testDeserializeAndSerializeNestedInterfacedObjectsWithTheClassMe
484483

485484
public function testExceptionWhenTypeIsNotKnownInDiscriminator()
486485
{
487-
$this->expectException(RuntimeException::class);
488-
$this->expectExceptionMessage('The type "second" has no mapped class for the abstract object "Symfony\Component\Serializer\Tests\Fixtures\DummyMessageInterface"');
489-
$this->serializerWithClassDiscriminator()->deserialize('{"type":"second","one":1}', DummyMessageInterface::class, 'json');
486+
try {
487+
$this->serializerWithClassDiscriminator()->deserialize('{"type":"second","one":1}', DummyMessageInterface::class, 'json');
488+
489+
$this->fail();
490+
} catch (\Throwable $e) {
491+
$this->assertInstanceOf(NotNormalizableValueException::class, $e);
492+
$this->assertSame('The type "second" is not a valid value.', $e->getMessage());
493+
$this->assertSame('string', $e->getCurrentType());
494+
$this->assertSame(['string'], $e->getExpectedTypes());
495+
$this->assertSame('type', $e->getPath());
496+
$this->assertTrue($e->canUseMessageForUser());
497+
}
490498
}
491499

492500
public function testExceptionWhenTypeIsNotInTheBodyToDeserialiaze()
493501
{
494-
$this->expectException(RuntimeException::class);
495-
$this->expectExceptionMessage('Type property "type" not found for the abstract object "Symfony\Component\Serializer\Tests\Fixtures\DummyMessageInterface"');
496-
$this->serializerWithClassDiscriminator()->deserialize('{"one":1}', DummyMessageInterface::class, 'json');
502+
try {
503+
$this->serializerWithClassDiscriminator()->deserialize('{"one":1}', DummyMessageInterface::class, 'json');
504+
505+
$this->fail();
506+
} catch (\Throwable $e) {
507+
$this->assertInstanceOf(NotNormalizableValueException::class, $e);
508+
$this->assertSame('Type property "type" not found for the abstract object "Symfony\Component\Serializer\Tests\Fixtures\DummyMessageInterface".', $e->getMessage());
509+
$this->assertSame('null', $e->getCurrentType());
510+
$this->assertSame(['string'], $e->getExpectedTypes());
511+
$this->assertSame('type', $e->getPath());
512+
$this->assertFalse($e->canUseMessageForUser());
513+
}
497514
}
498515

499516
public function testNotNormalizableValueExceptionMessageForAResource()
@@ -744,7 +761,9 @@ public function testCollectDenormalizationErrors()
744761
"string": null
745762
}
746763
],
747-
"php74FullWithConstructor": {}
764+
"php74FullWithConstructor": {},
765+
"dummyMessage": {
766+
}
748767
}';
749768

750769
$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
@@ -893,6 +912,15 @@ public function testCollectDenormalizationErrors()
893912
'useMessageForUser' => true,
894913
'message' => 'Failed to create object because the object miss the "constructorArgument" property.',
895914
],
915+
[
916+
'currentType' => 'null',
917+
'expectedTypes' => [
918+
'string',
919+
],
920+
'path' => 'dummyMessage.type',
921+
'useMessageForUser' => false,
922+
'message' => 'Type property "type" not found for the abstract object "Symfony\Component\Serializer\Tests\Fixtures\DummyMessageInterface".',
923+
],
896924
];
897925

898926
$this->assertSame($expected, $exceptionsAsArray);

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.