Skip to content

Commit a5102d9

Browse files
Cafeine42Thibaut Cholleysoyuka
authored
fix(schema): anyOf must contains an array, not an object (#7399)
Co-authored-by: Thibaut Cholley <[email protected]> Co-authored-by: soyuka <[email protected]>
1 parent 3b0c441 commit a5102d9

File tree

3 files changed

+54
-9
lines changed

3 files changed

+54
-9
lines changed

src/JsonSchema/Metadata/Property/Factory/SchemaPropertyMetadataFactory.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ private function getJsonSchemaFromType(Type $type, ?bool $readableLink = null):
218218
} elseif (1 === \count($schemas)) {
219219
$schema = current($schemas);
220220
} else {
221-
$schema = ['anyOf' => $schemas];
221+
$schema = ['anyOf' => array_values($schemas)];
222222
}
223223

224224
return $this->applyNullability($schema, $isNullable);
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <[email protected]>
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\JsonSchema\Tests\Fixtures;
15+
16+
use ApiPlatform\Metadata\ApiResource;
17+
18+
#[ApiResource]
19+
class DummyWithUnionTypeProperty
20+
{
21+
public string|int $unionProperty;
22+
}

src/JsonSchema/Tests/Metadata/Property/Factory/SchemaPropertyMetadataFactoryTest.php

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use ApiPlatform\JsonSchema\Metadata\Property\Factory\SchemaPropertyMetadataFactory;
1717
use ApiPlatform\JsonSchema\Tests\Fixtures\DummyWithCustomOpenApiContext;
1818
use ApiPlatform\JsonSchema\Tests\Fixtures\DummyWithEnum;
19+
use ApiPlatform\JsonSchema\Tests\Fixtures\DummyWithUnionTypeProperty;
1920
use ApiPlatform\JsonSchema\Tests\Fixtures\Enum\IntEnumAsIdentifier;
2021
use ApiPlatform\Metadata\ApiProperty;
2122
use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
@@ -115,10 +116,11 @@ public function testWithCustomOpenApiContextWithoutTypeDefinitionLegacy(): void
115116
public function testWithCustomOpenApiContextWithoutTypeDefinition(): void
116117
{
117118
$resourceClassResolver = $this->createMock(ResourceClassResolverInterface::class);
118-
$apiProperty = new ApiProperty(
119-
openapiContext: ['description' => 'My description'],
120-
nativeType: Type::bool(),
121-
);
119+
$apiProperty =
120+
new ApiProperty(
121+
openapiContext: ['description' => 'My description'],
122+
nativeType: Type::bool(),
123+
);
122124
$decorated = $this->createMock(PropertyMetadataFactoryInterface::class);
123125
$decorated->expects($this->once())->method('create')->with(DummyWithCustomOpenApiContext::class, 'foo')->willReturn($apiProperty);
124126
$schemaPropertyMetadataFactory = new SchemaPropertyMetadataFactory($resourceClassResolver, $decorated);
@@ -127,10 +129,11 @@ public function testWithCustomOpenApiContextWithoutTypeDefinition(): void
127129
'type' => 'boolean',
128130
], $apiProperty->getSchema());
129131

130-
$apiProperty = new ApiProperty(
131-
openapiContext: ['iris' => 'https://schema.org/Date'],
132-
nativeType: Type::object(\DateTimeImmutable::class),
133-
);
132+
$apiProperty =
133+
new ApiProperty(
134+
openapiContext: ['iris' => 'https://schema.org/Date'],
135+
nativeType: Type::object(\DateTimeImmutable::class),
136+
);
134137
$decorated = $this->createMock(PropertyMetadataFactoryInterface::class);
135138
$decorated->expects($this->once())->method('create')->with(DummyWithCustomOpenApiContext::class, 'bar')->willReturn($apiProperty);
136139
$schemaPropertyMetadataFactory = new SchemaPropertyMetadataFactory($resourceClassResolver, $decorated);
@@ -140,4 +143,24 @@ public function testWithCustomOpenApiContextWithoutTypeDefinition(): void
140143
'format' => 'date-time',
141144
], $apiProperty->getSchema());
142145
}
146+
147+
public function testUnionTypeAnyOfIsArray(): void
148+
{
149+
$resourceClassResolver = $this->createMock(ResourceClassResolverInterface::class);
150+
$apiProperty = new ApiProperty(nativeType: Type::union(Type::string(), Type::int()));
151+
$decorated = $this->createMock(PropertyMetadataFactoryInterface::class);
152+
$decorated->expects($this->once())->method('create')->with(DummyWithUnionTypeProperty::class, 'unionProperty')->willReturn($apiProperty);
153+
154+
$schemaPropertyMetadataFactory = new SchemaPropertyMetadataFactory($resourceClassResolver, $decorated);
155+
$apiProperty = $schemaPropertyMetadataFactory->create(DummyWithUnionTypeProperty::class, 'unionProperty');
156+
157+
$expectedSchema = [
158+
'anyOf' => [
159+
['type' => 'integer'],
160+
['type' => 'string'],
161+
],
162+
];
163+
164+
$this->assertEquals($expectedSchema, $apiProperty->getSchema());
165+
}
143166
}

0 commit comments

Comments
 (0)