Skip to content

Navigation Menu

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 c4388b6

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

File tree

3 files changed

+50
-10
lines changed
Filter options

3 files changed

+50
-10
lines changed

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php
+13-3Lines changed: 13 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,23 @@ 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(
279+
sprintf('Type property "%s" not found for the abstract object "%s".', $mapping->getTypeProperty(), $class),
280+
null,
281+
['string'],
282+
isset($context['deserialization_path']) ? $context['deserialization_path'].'.'.$mapping->getTypeProperty() : $mapping->getTypeProperty(),
283+
);
280284
}
281285

282286
$type = $data[$mapping->getTypeProperty()];
283287
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));
288+
throw NotNormalizableValueException::createForUnexpectedDataType(
289+
sprintf('The type "%s" is not a valid value.', $type),
290+
$type,
291+
['string'],
292+
isset($context['']) ? $context['deserialization_path'].'.'.$mapping->getTypeProperty() : $mapping->getTypeProperty(),
293+
true
294+
);
285295
}
286296

287297
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-7Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -484,16 +484,34 @@ public function testDeserializeAndSerializeNestedInterfacedObjectsWithTheClassMe
484484

485485
public function testExceptionWhenTypeIsNotKnownInDiscriminator()
486486
{
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');
487+
try {
488+
$this->serializerWithClassDiscriminator()->deserialize('{"type":"second","one":1}', DummyMessageInterface::class, 'json');
489+
490+
$this->fail();
491+
} catch (\Throwable $e) {
492+
$this->assertInstanceOf(NotNormalizableValueException::class, $e);
493+
$this->assertSame('The type "second" is not a valid value.', $e->getMessage());
494+
$this->assertSame('string', $e->getCurrentType());
495+
$this->assertSame(['string'], $e->getExpectedTypes());
496+
$this->assertSame('type', $e->getPath());
497+
$this->assertTrue($e->canUseMessageForUser());
498+
}
490499
}
491500

492501
public function testExceptionWhenTypeIsNotInTheBodyToDeserialiaze()
493502
{
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');
503+
try {
504+
$this->serializerWithClassDiscriminator()->deserialize('{"one":1}', DummyMessageInterface::class, 'json');
505+
506+
$this->fail();
507+
} catch (\Throwable $e) {
508+
$this->assertInstanceOf(NotNormalizableValueException::class, $e);
509+
$this->assertSame('Type property "type" not found for the abstract object "Symfony\Component\Serializer\Tests\Fixtures\DummyMessageInterface".', $e->getMessage());
510+
$this->assertSame('null', $e->getCurrentType());
511+
$this->assertSame(['string'], $e->getExpectedTypes());
512+
$this->assertSame('type', $e->getPath());
513+
$this->assertFalse($e->canUseMessageForUser());
514+
}
497515
}
498516

499517
public function testNotNormalizableValueExceptionMessageForAResource()
@@ -744,7 +762,9 @@ public function testCollectDenormalizationErrors()
744762
"string": null
745763
}
746764
],
747-
"php74FullWithConstructor": {}
765+
"php74FullWithConstructor": {},
766+
"dummyMessage": {
767+
}
748768
}';
749769

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

898927
$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.