Skip to content

Commit 97f889e

Browse files
ili101soyuka
authored andcommitted
fix(jsonld): allow @id, @context and @type when denormalizing
1 parent c7f25dc commit 97f889e

File tree

2 files changed

+46
-1
lines changed

2 files changed

+46
-1
lines changed

features/main/standard_put.feature

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,32 @@ Feature: Spec-compliant PUT support
2626
}
2727
"""
2828

29+
Scenario: Create a new resource with json-ld attributes
30+
When I add "Content-Type" header equal to "application/ld+json"
31+
And I send a "PUT" request to "/standard_puts/6" with body:
32+
"""
33+
{
34+
"@id": "/standard_puts/6",
35+
"@context": "/contexts/StandardPut",
36+
"@type": "StandardPut",
37+
"foo": "a",
38+
"bar": "b"
39+
}
40+
"""
41+
Then the response status code should be 201
42+
And the response should be in JSON
43+
And the JSON should be equal to:
44+
"""
45+
{
46+
"@context": "/contexts/StandardPut",
47+
"@id": "/standard_puts/6",
48+
"@type": "StandardPut",
49+
"id": 6,
50+
"foo": "a",
51+
"bar": "b"
52+
}
53+
"""
54+
2955
Scenario: Replace an existing resource
3056
When I add "Content-Type" header equal to "application/ld+json"
3157
And I send a "PUT" request to "/standard_puts/5" with body:

src/JsonLd/Serializer/ItemNormalizer.php

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@
1717
use ApiPlatform\Api\ResourceClassResolverInterface as LegacyResourceClassResolverInterface;
1818
use ApiPlatform\JsonLd\AnonymousContextBuilderInterface;
1919
use ApiPlatform\JsonLd\ContextBuilderInterface;
20+
use ApiPlatform\Metadata\Exception\ItemNotFoundException;
2021
use ApiPlatform\Metadata\HttpOperation;
2122
use ApiPlatform\Metadata\IriConverterInterface;
2223
use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
2324
use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface;
25+
use ApiPlatform\Metadata\Put;
2426
use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface;
2527
use ApiPlatform\Metadata\ResourceAccessCheckerInterface;
2628
use ApiPlatform\Metadata\ResourceClassResolverInterface;
@@ -148,9 +150,26 @@ public function denormalize(mixed $data, string $class, ?string $format = null,
148150
throw new NotNormalizableValueException('Update is not allowed for this operation.');
149151
}
150152

151-
$context[self::OBJECT_TO_POPULATE] = $this->iriConverter->getResourceFromIri($data['@id'], $context + ['fetch_data' => true]);
153+
try {
154+
$context[self::OBJECT_TO_POPULATE] = $this->iriConverter->getResourceFromIri($data['@id'], $context + ['fetch_data' => true]);
155+
} catch (ItemNotFoundException $e) {
156+
$operation = $context['operation'] ?? null;
157+
if (!($operation instanceof Put && ($operation->getExtraProperties()['standard_put'] ?? false))) {
158+
throw $e;
159+
}
160+
}
152161
}
153162

154163
return parent::denormalize($data, $class, $format, $context);
155164
}
165+
166+
protected function getAllowedAttributes(string|object $classOrObject, array $context, bool $attributesAsString = false): array|bool
167+
{
168+
$allowedAttributes = parent::getAllowedAttributes($classOrObject, $context, $attributesAsString);
169+
if (\is_array($allowedAttributes) && ($context['api_denormalize'] ?? false)) {
170+
$allowedAttributes = array_merge($allowedAttributes, ['@id', '@type', '@context']);
171+
}
172+
173+
return $allowedAttributes;
174+
}
156175
}

0 commit comments

Comments
 (0)