Skip to content

Commit 5c62c1b

Browse files
authored
fix(jsonapi): do not require id in input schema for post operations (#8252)
Fixes #6738
1 parent a6bdf71 commit 5c62c1b

2 files changed

Lines changed: 30 additions & 1 deletion

File tree

src/JsonApi/JsonSchema/SchemaFactory.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use ApiPlatform\JsonSchema\SchemaFactoryAwareInterface;
2121
use ApiPlatform\JsonSchema\SchemaFactoryInterface;
2222
use ApiPlatform\JsonSchema\SchemaUriPrefixTrait;
23+
use ApiPlatform\Metadata\HttpOperation;
2324
use ApiPlatform\Metadata\Operation;
2425
use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
2526
use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface;
@@ -369,11 +370,14 @@ private function buildDefinitionPropertiesSchema(string $key, string $className,
369370
];
370371
}
371372

373+
// https://jsonapi.org/format/#crud-creating — clients MAY supply an id when creating a resource.
374+
$required = $operation instanceof HttpOperation && 'POST' === $operation->getMethod() ? ['type'] : ['type', 'id'];
375+
372376
return [
373377
'data' => [
374378
'type' => 'object',
375379
'properties' => $replacement,
376-
'required' => ['type', 'id'],
380+
'required' => $required,
377381
],
378382
] + $included;
379383
}

src/JsonApi/Tests/JsonSchema/SchemaFactoryTest.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
use ApiPlatform\Metadata\Get;
2323
use ApiPlatform\Metadata\GetCollection;
2424
use ApiPlatform\Metadata\Operations;
25+
use ApiPlatform\Metadata\Patch;
26+
use ApiPlatform\Metadata\Post;
2527
use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
2628
use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface;
2729
use ApiPlatform\Metadata\Property\PropertyNameCollection;
@@ -49,6 +51,7 @@ protected function setUp(): void
4951
);
5052
$propertyNameCollectionFactory = $this->prophesize(PropertyNameCollectionFactoryInterface::class);
5153
$propertyNameCollectionFactory->create(Dummy::class, ['enable_getter_setter_extraction' => true, 'schema_type' => Schema::TYPE_OUTPUT])->willReturn(new PropertyNameCollection());
54+
$propertyNameCollectionFactory->create(Dummy::class, ['enable_getter_setter_extraction' => true, 'schema_type' => Schema::TYPE_INPUT])->willReturn(new PropertyNameCollection());
5255
$propertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class);
5356

5457
$definitionNameFactory = new DefinitionNameFactory(null);
@@ -164,4 +167,26 @@ public function testSchemaTypeBuildSchema(): void
164167
$forcedCollection = $this->schemaFactory->buildSchema(Dummy::class, 'jsonapi', Schema::TYPE_OUTPUT, forceCollection: true);
165168
$this->assertEquals($resultSchema['allOf'][0]['$ref'], $forcedCollection['allOf'][0]['$ref']);
166169
}
170+
171+
public function testPostInputSchemaDoesNotRequireId(): void
172+
{
173+
$resultSchema = $this->schemaFactory->buildSchema(Dummy::class, 'jsonapi', Schema::TYPE_INPUT, new Post());
174+
$definitions = $resultSchema->getDefinitions();
175+
$rootDefinitionKey = $resultSchema->getRootDefinitionKey();
176+
177+
$this->assertTrue(isset($definitions[$rootDefinitionKey]['properties']['data']));
178+
$data = $definitions[$rootDefinitionKey]['properties']['data'];
179+
$this->assertArrayHasKey('required', $data);
180+
$this->assertSame(['type'], $data['required']);
181+
}
182+
183+
public function testPatchInputSchemaRequiresId(): void
184+
{
185+
$resultSchema = $this->schemaFactory->buildSchema(Dummy::class, 'jsonapi', Schema::TYPE_INPUT, new Patch());
186+
$definitions = $resultSchema->getDefinitions();
187+
$rootDefinitionKey = $resultSchema->getRootDefinitionKey();
188+
189+
$data = $definitions[$rootDefinitionKey]['properties']['data'];
190+
$this->assertSame(['type', 'id'], $data['required']);
191+
}
167192
}

0 commit comments

Comments
 (0)