From bc625680ae1596946eaf12c217876effe7d75edf Mon Sep 17 00:00:00 2001 From: Takashi Kanemoto Date: Wed, 29 Oct 2025 12:44:40 +0900 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20=F0=9F=90=9B=20fallback=20the=20sche?= =?UTF-8?q?ma=20for=20`mixed`=20properties=20to=20`string|null`=20instead?= =?UTF-8?q?=20of=20`null`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Metadata/Property/Factory/SchemaPropertyMetadataFactory.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/JsonSchema/Metadata/Property/Factory/SchemaPropertyMetadataFactory.php b/src/JsonSchema/Metadata/Property/Factory/SchemaPropertyMetadataFactory.php index cf41fbed56..90f8ddea3f 100644 --- a/src/JsonSchema/Metadata/Property/Factory/SchemaPropertyMetadataFactory.php +++ b/src/JsonSchema/Metadata/Property/Factory/SchemaPropertyMetadataFactory.php @@ -280,6 +280,7 @@ private function getJsonSchemaFromType(Type $type, ?bool $readableLink = null): TypeIdentifier::OBJECT => ['type' => 'object'], TypeIdentifier::RESOURCE => ['type' => 'string'], TypeIdentifier::CALLABLE => ['type' => 'string'], + TypeIdentifier::MIXED => ['type' => 'string'], default => ['type' => 'null'], }; From fdc9afe64632398e4ce6924977e7f93b0ab5c4aa Mon Sep 17 00:00:00 2001 From: Takashi Kanemoto Date: Wed, 29 Oct 2025 13:42:07 +0900 Subject: [PATCH 2/2] =?UTF-8?q?test:=20=F0=9F=92=8D=20add=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Tests/Fixtures/DummyWithMixed.php | 23 +++++++++++++ .../SchemaPropertyMetadataFactoryTest.php | 34 +++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 src/JsonSchema/Tests/Fixtures/DummyWithMixed.php diff --git a/src/JsonSchema/Tests/Fixtures/DummyWithMixed.php b/src/JsonSchema/Tests/Fixtures/DummyWithMixed.php new file mode 100644 index 0000000000..3703a17d94 --- /dev/null +++ b/src/JsonSchema/Tests/Fixtures/DummyWithMixed.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\JsonSchema\Tests\Fixtures; + +use ApiPlatform\Metadata\ApiResource; + +#[ApiResource] +class DummyWithMixed +{ + public mixed $mixedProperty; + public array $mixedArrayProperty; +} diff --git a/src/JsonSchema/Tests/Metadata/Property/Factory/SchemaPropertyMetadataFactoryTest.php b/src/JsonSchema/Tests/Metadata/Property/Factory/SchemaPropertyMetadataFactoryTest.php index ce930485a0..70b5f81b6b 100644 --- a/src/JsonSchema/Tests/Metadata/Property/Factory/SchemaPropertyMetadataFactoryTest.php +++ b/src/JsonSchema/Tests/Metadata/Property/Factory/SchemaPropertyMetadataFactoryTest.php @@ -16,6 +16,7 @@ use ApiPlatform\JsonSchema\Metadata\Property\Factory\SchemaPropertyMetadataFactory; use ApiPlatform\JsonSchema\Tests\Fixtures\DummyWithCustomOpenApiContext; use ApiPlatform\JsonSchema\Tests\Fixtures\DummyWithEnum; +use ApiPlatform\JsonSchema\Tests\Fixtures\DummyWithMixed; use ApiPlatform\JsonSchema\Tests\Fixtures\DummyWithUnionTypeProperty; use ApiPlatform\JsonSchema\Tests\Fixtures\Enum\IntEnumAsIdentifier; use ApiPlatform\Metadata\ApiProperty; @@ -167,4 +168,37 @@ public function testUnionTypeAnyOfIsArray(): void $this->assertEquals($expectedSchema, $apiProperty->getSchema()); } + + public function testMixed(): void + { + if (!method_exists(PropertyInfoExtractor::class, 'getType')) { // @phpstan-ignore-line symfony/property-info 6.4 is still allowed and this may be true + $this->markTestSkipped('This test only supports type-info component'); + } + + $resourceClassResolver = $this->createMock(ResourceClassResolverInterface::class); + $apiProperty = new ApiProperty(nativeType: Type::mixed()); + $decorated = $this->createMock(PropertyMetadataFactoryInterface::class); + $decorated->expects($this->once())->method('create')->with(DummyWithMixed::class, 'mixedProperty')->willReturn($apiProperty); + + $schemaPropertyMetadataFactory = new SchemaPropertyMetadataFactory($resourceClassResolver, $decorated); + $apiProperty = $schemaPropertyMetadataFactory->create(DummyWithMixed::class, 'mixedProperty'); + + $this->assertEquals([ + 'type' => ['string', 'null'], + ], $apiProperty->getSchema()); + + $apiProperty = new ApiProperty(nativeType: Type::array(Type::mixed())); + $decorated = $this->createMock(PropertyMetadataFactoryInterface::class); + $decorated->expects($this->once())->method('create')->with(DummyWithMixed::class, 'mixedArrayProperty')->willReturn($apiProperty); + + $schemaPropertyMetadataFactory = new SchemaPropertyMetadataFactory($resourceClassResolver, $decorated); + $apiProperty = $schemaPropertyMetadataFactory->create(DummyWithMixed::class, 'mixedArrayProperty'); + + $this->assertEquals([ + 'type' => 'array', + 'items' => [ + 'type' => ['string', 'null'], + ], + ], $apiProperty->getSchema()); + } }