Skip to content

Commit 43e3b4c

Browse files
authored
fix(openapi): don't apply the global name converter to the generated document (#8360)
1 parent f1f33ca commit 43e3b4c

2 files changed

Lines changed: 94 additions & 1 deletion

File tree

src/Symfony/Bundle/Resources/config/openapi.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,11 @@
2929
return function (ContainerConfigurator $container) {
3030
$services = $container->services();
3131

32+
$services->set('api_platform.openapi.name_converter')
33+
->parent('serializer.name_converter.metadata_aware.abstract');
34+
3235
$services->set('api_platform.openapi.normalizer', OpenApiNormalizer::class)
33-
->args([inline_service(Serializer::class)->arg(0, [inline_service(ObjectNormalizer::class)->arg(0, service('serializer.mapping.class_metadata_factory'))->arg(1, service('serializer.name_converter.metadata_aware'))->arg(2, service('api_platform.property_accessor'))->arg(3, service('api_platform.property_info'))])->arg(1, [service('serializer.encoder.json')])])
36+
->args([inline_service(Serializer::class)->arg(0, [inline_service(ObjectNormalizer::class)->arg(0, service('serializer.mapping.class_metadata_factory'))->arg(1, service('api_platform.openapi.name_converter'))->arg(2, service('api_platform.property_accessor'))->arg(3, service('api_platform.property_info'))])->arg(1, [service('serializer.encoder.json')])])
3437
->tag('serializer.normalizer', ['priority' => -795]);
3538

3639
$services->alias(OpenApiNormalizer::class, 'api_platform.openapi.normalizer');
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
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\Functional;
15+
16+
use ApiPlatform\Symfony\Bundle\Test\ApiTestCase;
17+
use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue8143\ReferenceResponse;
18+
use ApiPlatform\Tests\SetupClassResourcesTrait;
19+
use Symfony\Component\Config\Loader\LoaderInterface;
20+
use Symfony\Component\DependencyInjection\ContainerBuilder;
21+
22+
class OpenApiNameConverterAppKernel extends \AppKernel
23+
{
24+
public function getCacheDir(): string
25+
{
26+
return parent::getCacheDir().'/openapi_name_converter';
27+
}
28+
29+
public function getLogDir(): string
30+
{
31+
return parent::getLogDir().'/openapi_name_converter';
32+
}
33+
34+
protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader): void
35+
{
36+
parent::configureContainer($c, $loader);
37+
38+
$loader->load(static function (ContainerBuilder $container): void {
39+
$container->loadFromExtension('framework', [
40+
'serializer' => [
41+
'name_converter' => 'serializer.name_converter.camel_case_to_snake_case',
42+
],
43+
]);
44+
});
45+
}
46+
}
47+
48+
final class OpenApiNameConverterTest extends ApiTestCase
49+
{
50+
use SetupClassResourcesTrait;
51+
52+
protected static ?bool $alwaysBootKernel = true;
53+
54+
/**
55+
* @return class-string[]
56+
*/
57+
public static function getResources(): array
58+
{
59+
return [ReferenceResponse::class];
60+
}
61+
62+
protected static function getKernelClass(): string
63+
{
64+
return OpenApiNameConverterAppKernel::class;
65+
}
66+
67+
public function testGlobalNameConverterDoesNotLeakIntoOpenApiDocument(): void
68+
{
69+
$response = self::createClient()->request('GET', '/docs', [
70+
'headers' => ['Accept' => 'application/vnd.openapi+json'],
71+
]);
72+
73+
$this->assertResponseIsSuccessful();
74+
$json = $response->toArray();
75+
$content = $response->getContent();
76+
77+
// OpenAPI keys must stay camelCase even when a global name converter is configured.
78+
$this->assertStringContainsString('"operationId"', $content);
79+
$this->assertStringNotContainsString('"operation_id"', $content);
80+
$this->assertStringNotContainsString('"extension_properties"', $content);
81+
$this->assertStringNotContainsString('"external_docs"', $content);
82+
$this->assertStringNotContainsString('"request_bodies"', $content);
83+
$this->assertStringNotContainsString('"security_schemes"', $content);
84+
85+
// The #[SerializedName('$ref')] metadata must still be honored.
86+
$responses = $json['paths']['/issue8143_reference_response']['post']['responses'];
87+
$this->assertArrayHasKey('$ref', $responses['401']);
88+
$this->assertSame('#/components/responses/401', $responses['401']['$ref']);
89+
}
90+
}

0 commit comments

Comments
 (0)