diff --git a/features/hydra/error.feature b/features/hydra/error.feature index d5fbe6ac71c..bafcf1f4b3c 100644 --- a/features/hydra/error.feature +++ b/features/hydra/error.feature @@ -139,3 +139,15 @@ Feature: Error handling And the JSON node "@id" should be equal to "/relation_embedders/1" And the JSON node "anotherRelated.@id" should be equal to "/related_dummies/1" And the JSON node "anotherRelated.symfony" should be equal to "phalcon" + + Scenario: Get an error because of sending bad type property + When I add "Content-Type" header equal to "application/json" + And I send a "POST" request to "/greetings" with body: + """ + { + "0": 1 + } + """ + Then the response status code should be 201 + And the response should be in JSON + And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8" diff --git a/features/jsonld/context.feature b/features/jsonld/context.feature index 6191e8aed08..49d76b7e3b6 100644 --- a/features/jsonld/context.feature +++ b/features/jsonld/context.feature @@ -40,7 +40,7 @@ Feature: JSON-LD contexts generation }, "jsonData": "Dummy/jsonData", "arrayData": "Dummy/arrayData", - "nameConverted": "Dummy/nameConverted", + "name_converted": "Dummy/name_converted", "name": "https://schema.org/name", "alias": "https://schema.org/alternateName", "foo": "Dummy/foo" diff --git a/src/Serializer/AbstractItemNormalizer.php b/src/Serializer/AbstractItemNormalizer.php index fff2d7b2708..1a2b70a08c2 100644 --- a/src/Serializer/AbstractItemNormalizer.php +++ b/src/Serializer/AbstractItemNormalizer.php @@ -222,13 +222,21 @@ public function denormalize(mixed $data, string $class, string $format = null, a return $object; } + $options = $this->getFactoryOptions($context); + $propertyNames = iterator_to_array($this->propertyNameCollectionFactory->create($resourceClass, $options)); + // Revert attributes that aren't allowed to be changed after a post-denormalize check foreach (array_keys($data) as $attribute) { + $attribute = $this->nameConverter ? $this->nameConverter->denormalize((string) $attribute) : $attribute; + if (!\in_array($attribute, $propertyNames, true)) { + continue; + } + if (!$this->canAccessAttributePostDenormalize($object, $previousObject, $attribute, $context)) { if (null !== $previousObject) { $this->setValue($object, $attribute, $this->propertyAccessor->getValue($previousObject, $attribute)); } else { - $propertyMetadata = $this->propertyMetadataFactory->create($resourceClass, $attribute, $this->getFactoryOptions($context)); + $propertyMetadata = $this->propertyMetadataFactory->create($resourceClass, $attribute, $options); $this->setValue($object, $attribute, $propertyMetadata->getDefault()); } } diff --git a/src/Symfony/Bundle/Resources/config/jsonld.xml b/src/Symfony/Bundle/Resources/config/jsonld.xml index 36f32ec8766..8bb2327df38 100644 --- a/src/Symfony/Bundle/Resources/config/jsonld.xml +++ b/src/Symfony/Bundle/Resources/config/jsonld.xml @@ -12,7 +12,7 @@ - null + diff --git a/tests/Serializer/ItemNormalizerTest.php b/tests/Serializer/ItemNormalizerTest.php index 102f99f036f..2283fd7b22e 100644 --- a/tests/Serializer/ItemNormalizerTest.php +++ b/tests/Serializer/ItemNormalizerTest.php @@ -143,7 +143,7 @@ public function testDenormalizeWithIri(): void { $context = ['resource_class' => Dummy::class, 'api_allow_update' => true]; - $propertyNameCollection = new PropertyNameCollection(['name']); + $propertyNameCollection = new PropertyNameCollection(['id', 'name']); $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyNameCollectionFactoryProphecy->create(Dummy::class, [])->willReturn($propertyNameCollection)->shouldBeCalled();