Hacktoberfest 2026:維護者為十月標記出來的 issue,仍然開放、適合新手。 瀏覽 Hacktoberfest issue

OpenAPI: Non-JSON formats should not generate JSON schemas

未關閉
#7,802 5 則留言 1 個 reaction 已指派 0 人 在 GitHub 檢視

維護者通常 1 天內回覆

還沒有人認領這個 Issue。

評估

難度
4/5
預估耗時
3-5 天
新手友好度
45/100
Issue 類型
缺陷
描述清晰度
描述清楚
活躍度
停滯
技術堆疊
openapi, php
領域
api

研究方向

從 src/OpenApi/Factory/OpenApiFactory.php 和 src/Symfony/Bundle/Resources/config/openapi.php 開始,接著檢查 ApiPlatformExtension.php 中如何計算 jsonschema_formats。更新非 JSON 回應格式的 OpenAPI 行為,並在 tests/OpenApi/Factory/OpenApiFactoryTest.php 中加入回歸案例;完成的標準是非 JSON 格式不再接收產生的 JSON schema。

由索引模型根據 Issue 內容生成。

描述

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:

  1. Not have a schema reference in OpenAPI
  2. 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.

主要語言
PHP
星號
2.6k
分支
984
平均合併
1 天 14 小時
30 天內合併 PR
87

環境準備

從這裡開始

  1. 先讀完整個 Issue,再讀專案的貢獻指南。
  2. 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
  3. Fork 儲存庫,在一個分支上完成修改。
  4. 送出 Pull Request,並在描述裡引用這個 Issue 編號。

api-platform/core 的其他 Issue

查看 api-platform/core 的全部 Issue

相似的 Issue

更多 PHP Issue

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。