OpenAPI: Non-JSON formats should not generate JSON schemas
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 45/100
Hướng nghiên cứu
Bắt đầu trong src/OpenApi/Factory/OpenApiFactory.php và src/Symfony/Bundle/Resources/config/openapi.php, sau đó kiểm tra cách jsonschema_formats được tính toán trong ApiPlatformExtension.php. Cập nhật hành vi của OpenAPI đối với các định dạng phản hồi không phải JSON và thêm trường hợp hồi quy trong tests/OpenApi/Factory/OpenApiFactoryTest.php; hoàn tất khi các định dạng không phải JSON không còn nhận các lược đồ JSON được tạo tự động.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Issue Description
When an API Platform operation defines non-JSON output formats (e.g., text/html, text/xml), the OpenAPI factory generates JSON schemas for these formats, which is semantically incorrect.
Example
#[ApiResource(
operations: [
new Get(
uriTemplate: '/unsubscribe/{token}',
formats: [
'jsonld' => ['application/ld+json'],
'json' => ['application/json'],
'html' => ['text/html'], // This causes the issue
],
),
],
)]
class UnsubscribedEmail {}
Current Behavior
The OpenAPI export generates:
paths:
/api/unsubscribe/{token}:
get:
responses:
'200':
content:
application/ld+json:
schema:
$ref: '#/components/schemas/UnsubscribedEmail.jsonld'
application/json:
schema:
$ref: '#/components/schemas/UnsubscribedEmail'
text/html:
schema:
$ref: '#/components/schemas/UnsubscribedEmail.html' # Makes no sense
components:
schemas:
UnsubscribedEmail.html: # JSON schema for HTML format - meaningless
type: object
properties:
status:
type: string
Expected Behavior
Non-JSON formats should either:
- Not have a
schemareference in OpenAPI - Or be excluded from the OpenAPI spec entirely (content negotiation still works at runtime)
Root Cause
In src/OpenApi/Factory/OpenApiFactory.php, the getMimeTypes() method returns ALL output formats, and the schema generation loop creates schemas for each:
// Lines 267-273
foreach ($responseMimeTypes as $operationFormat) {
$operationOutputSchema = $this->jsonSchemaFactory->buildSchema(
$resourceClass,
$operationFormat, // <-- Includes 'html', 'xml', etc.
Schema::TYPE_OUTPUT,
$operation,
$schema,
null,
$forceSchemaCollection
);
$operationOutputSchemas[$operationFormat] = $operationOutputSchema;
}
Proposed Fix
Use the existing jsonschema_formats configuration parameter to filter which formats get JSON schemas in OpenAPI.
Step 1: Inject jsonschema_formats into OpenApiFactory
In src/Symfony/Bundle/Resources/config/openapi.php:
$services->set('api_platform.openapi.factory', OpenApiFactory::class)
->args([
// ... existing args ...
'%api_platform.jsonschema_formats%', // Add this parameter
]);
Step 2: Update OpenApiFactory constructor
public function __construct(
// ... existing parameters ...
private readonly array $jsonSchemaFormats = [],
) {
// ...
}
Step 3: Filter formats in schema generation loop
// Around line 267
foreach ($responseMimeTypes as $mimeType => $operationFormat) {
// Skip formats that don't have JSON schema support
if (!isset($this->jsonSchemaFormats[$operationFormat])) {
continue;
}
$operationOutputSchema = $this->jsonSchemaFactory->buildSchema(
$resourceClass,
$operationFormat,
Schema::TYPE_OUTPUT,
$operation,
$schema,
null,
$forceSchemaCollection
);
$operationOutputSchemas[$operationFormat] = $operationOutputSchema;
}
Step 4: Update buildContent to handle missing schemas
private function buildContent(array $responseMimeTypes, array $operationSchemas): \ArrayObject
{
$content = new \ArrayObject();
foreach ($responseMimeTypes as $mimeType => $format) {
// Only add content entry if we have a schema for this format
if (isset($operationSchemas[$format])) {
$content[$mimeType] = new MediaType(
schema: new \ArrayObject($operationSchemas[$format]->getArrayCopy(false))
);
}
// Non-JSON formats without schemas are simply not included in OpenAPI content
}
return $content;
}
Alternative Consideration
The buildContent method could instead add the content type without a schema reference:
if (isset($operationSchemas[$format])) {
$content[$mimeType] = new MediaType(schema: new \ArrayObject($operationSchemas[$format]->getArrayCopy(false)));
} else {
// Include the content type but without a schema (valid in OpenAPI 3.1)
$content[$mimeType] = new MediaType();
}
This preserves the information that the endpoint supports HTML responses, just without a JSON schema.
Testing
Add a test case to tests/OpenApi/Factory/OpenApiFactoryTest.php:
public function testNonJsonFormatsDoNotGenerateSchemas(): void
{
// Create a resource with html format
// Assert that UnsubscribedEmail.html schema does not exist
// Assert that text/html content type either has no schema or is not present
}
Configuration Reference
The jsonschema_formats is already computed in ApiPlatformExtension.php:
$jsonSchemaFormats = $config['jsonschema_formats'];
if (!$jsonSchemaFormats) {
foreach (array_merge(array_keys($formats), array_keys($errorFormats)) as $f) {
// Only JSON-based formats get schemas by default
if (str_starts_with($f, 'json')) {
$jsonSchemaFormats[$f] = true;
}
}
}
This logic already correctly identifies JSON formats - it just needs to be used in OpenApiFactory.
- Ngôn ngữ chính
- PHP
- Star
- 2.6k
- Fork
- 987
- Merge trung bình
- 1 ngày 8 giờ
- Pull request đã merge (30 ngày)
- 80
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của api-platform/core
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
api-platform/core#8665 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Doctrine\Orm\OrderExtension fails on SortDirectionCó thể đã có người làm Có pull request liên kết đang mở hoặc đã được merge. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
api-platform/core#8660 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
DeserializeProvider calls PartialDenormalizationException::getErrors(), deprecated in Symfony 8.1Có thể đã có người làm Có pull request liên kết đang mở hoặc đã được merge. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
api-platform/core#8650 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
api-platform/core#8649 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
`OrderExtension` and `OrderFilter` pass string sort directions, deprecated since `doctrine/orm` 3.7Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
api-platform/core#8648 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của api-platform/core
Issue tương tự
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 65/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
Maintainer thường phản hồi trong vòng 2 ngày
-
b:1.9 t:enhancement
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 65/100
Maintainer thường phản hồi trong vòng 3 ngày
-
backend bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100