Skip to content

Commit 07babd8

Browse files
authored
fix(jsonschema): nested gen_id follows the property (#8644)
The first relation's gen_id stuck to every deeper embedded definition, while the serializer lets each property's genId win and only inherits when it is null. Schemas then advertised `@id` (or not) differently from the payload.
1 parent dab2e7c commit 07babd8

9 files changed

Lines changed: 388 additions & 1 deletion

File tree

‎src/JsonSchema/SchemaFactory.php‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ private function buildPropertySchema(Schema $schema, string $definitionName, str
314314
continue;
315315
}
316316

317-
$childSerializerContext = $serializerContext + [self::FORCE_SUBSCHEMA => true, 'gen_id' => $propertyMetadata->getGenId() ?? true];
317+
$childSerializerContext = [self::FORCE_SUBSCHEMA => true, 'gen_id' => $propertyMetadata->getGenId() ?? ($serializerContext['gen_id'] ?? true)] + $serializerContext;
318318
if (isset($serializerContext[AbstractNormalizer::ATTRIBUTES])) {
319319
$attributes = $serializerContext[AbstractNormalizer::ATTRIBUTES];
320320
if (\is_array($attributes) && \array_key_exists($normalizedPropertyName, $attributes) && \is_array($attributes[$normalizedPropertyName])) {
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <dunglas@gmail.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonSchemaGenIdChain;
15+
16+
use ApiPlatform\Metadata\ApiProperty;
17+
use ApiPlatform\Metadata\ApiResource;
18+
use ApiPlatform\Metadata\Get;
19+
use Symfony\Component\Serializer\Attribute\Groups;
20+
21+
#[ApiResource(operations: [
22+
new Get(
23+
uriTemplate: '/json_schema_gen_id_chain/inverse_middles/{id}',
24+
normalizationContext: ['groups' => ['chain:read']],
25+
provider: [self::class, 'provide'],
26+
),
27+
])]
28+
class GenIdChainInverseMiddle
29+
{
30+
#[ApiProperty(identifier: true)]
31+
#[Groups(['chain:read'])]
32+
public ?int $id = null;
33+
34+
#[ApiProperty(genId: false)]
35+
#[Groups(['chain:read'])]
36+
public ?GenIdChainLeaf $second = null;
37+
38+
public static function provide(): ?self
39+
{
40+
return null;
41+
}
42+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <dunglas@gmail.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonSchemaGenIdChain;
15+
16+
use ApiPlatform\Metadata\ApiProperty;
17+
use ApiPlatform\Metadata\ApiResource;
18+
use ApiPlatform\Metadata\Get;
19+
use Symfony\Component\Serializer\Attribute\Groups;
20+
21+
#[ApiResource(operations: [
22+
new Get(
23+
uriTemplate: '/json_schema_gen_id_chain/inverse_roots/{id}',
24+
normalizationContext: ['groups' => ['chain:read']],
25+
provider: [self::class, 'provide'],
26+
),
27+
])]
28+
class GenIdChainInverseRoot
29+
{
30+
#[ApiProperty(identifier: true)]
31+
#[Groups(['chain:read'])]
32+
public ?int $id = null;
33+
34+
#[ApiProperty(genId: true)]
35+
#[Groups(['chain:read'])]
36+
public ?GenIdChainInverseMiddle $first = null;
37+
38+
public static function provide(): ?self
39+
{
40+
return null;
41+
}
42+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <dunglas@gmail.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonSchemaGenIdChain;
15+
16+
use ApiPlatform\Metadata\ApiProperty;
17+
use ApiPlatform\Metadata\ApiResource;
18+
use ApiPlatform\Metadata\Get;
19+
use Symfony\Component\Serializer\Attribute\Groups;
20+
21+
#[ApiResource(operations: [
22+
new Get(
23+
uriTemplate: '/json_schema_gen_id_chain/leaves/{id}',
24+
normalizationContext: ['groups' => ['chain:read']],
25+
provider: [self::class, 'provide'],
26+
),
27+
])]
28+
class GenIdChainLeaf
29+
{
30+
#[ApiProperty(identifier: true)]
31+
#[Groups(['chain:read'])]
32+
public ?int $id = null;
33+
34+
#[Groups(['chain:read'])]
35+
public ?string $label = null;
36+
37+
public static function provide(): ?self
38+
{
39+
return null;
40+
}
41+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <dunglas@gmail.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonSchemaGenIdChain;
15+
16+
use ApiPlatform\Metadata\ApiProperty;
17+
use ApiPlatform\Metadata\ApiResource;
18+
use ApiPlatform\Metadata\Get;
19+
use Symfony\Component\Serializer\Attribute\Groups;
20+
21+
#[ApiResource(operations: [
22+
new Get(
23+
uriTemplate: '/json_schema_gen_id_chain/middles/{id}',
24+
normalizationContext: ['groups' => ['chain:read']],
25+
provider: [self::class, 'provide'],
26+
),
27+
])]
28+
class GenIdChainMiddle
29+
{
30+
#[ApiProperty(identifier: true)]
31+
#[Groups(['chain:read'])]
32+
public ?int $id = null;
33+
34+
#[ApiProperty(genId: true)]
35+
#[Groups(['chain:read'])]
36+
public ?GenIdChainLeaf $second = null;
37+
38+
public static function provide(): ?self
39+
{
40+
return null;
41+
}
42+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <dunglas@gmail.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonSchemaGenIdChain;
15+
16+
use ApiPlatform\Metadata\ApiProperty;
17+
use ApiPlatform\Metadata\ApiResource;
18+
use ApiPlatform\Metadata\Get;
19+
use Symfony\Component\Serializer\Attribute\Groups;
20+
21+
#[ApiResource(operations: [
22+
new Get(
23+
uriTemplate: '/json_schema_gen_id_chain/null_middles/{id}',
24+
normalizationContext: ['groups' => ['chain:read']],
25+
provider: [self::class, 'provide'],
26+
),
27+
])]
28+
class GenIdChainNullMiddle
29+
{
30+
#[ApiProperty(identifier: true)]
31+
#[Groups(['chain:read'])]
32+
public ?int $id = null;
33+
34+
#[Groups(['chain:read'])]
35+
public ?GenIdChainLeaf $second = null;
36+
37+
public static function provide(): ?self
38+
{
39+
return null;
40+
}
41+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <dunglas@gmail.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonSchemaGenIdChain;
15+
16+
use ApiPlatform\Metadata\ApiProperty;
17+
use ApiPlatform\Metadata\ApiResource;
18+
use ApiPlatform\Metadata\Get;
19+
use Symfony\Component\Serializer\Attribute\Groups;
20+
21+
#[ApiResource(operations: [
22+
new Get(
23+
uriTemplate: '/json_schema_gen_id_chain/null_roots/{id}',
24+
normalizationContext: ['groups' => ['chain:read']],
25+
provider: [self::class, 'provide'],
26+
),
27+
])]
28+
class GenIdChainNullRoot
29+
{
30+
#[ApiProperty(identifier: true)]
31+
#[Groups(['chain:read'])]
32+
public ?int $id = null;
33+
34+
#[ApiProperty(genId: false)]
35+
#[Groups(['chain:read'])]
36+
public ?GenIdChainNullMiddle $first = null;
37+
38+
public static function provide(): ?self
39+
{
40+
return null;
41+
}
42+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <dunglas@gmail.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\JsonSchemaGenIdChain;
15+
16+
use ApiPlatform\Metadata\ApiProperty;
17+
use ApiPlatform\Metadata\ApiResource;
18+
use ApiPlatform\Metadata\Get;
19+
use Symfony\Component\Serializer\Attribute\Groups;
20+
21+
#[ApiResource(operations: [
22+
new Get(
23+
uriTemplate: '/json_schema_gen_id_chain/roots/{id}',
24+
normalizationContext: ['groups' => ['chain:read']],
25+
provider: [self::class, 'provide'],
26+
),
27+
])]
28+
class GenIdChainRoot
29+
{
30+
#[ApiProperty(identifier: true)]
31+
#[Groups(['chain:read'])]
32+
public ?int $id = null;
33+
34+
#[ApiProperty(genId: false)]
35+
#[Groups(['chain:read'])]
36+
public ?GenIdChainMiddle $first = null;
37+
38+
public static function provide(): ?self
39+
{
40+
return null;
41+
}
42+
}

0 commit comments

Comments
 (0)