Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

OpenAPI: Support for JSON-LD Only APIs

未关闭
#7,803 1 条评论 2 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 1 天内回复

还没有人认领这个 Issue。

评估

难度
5/5
预计耗时
一周以上
新手友好度
38/100
Issue 类型
功能
描述清晰度
基本清楚
活跃度
冷清
技术栈
openapi, php, symfony
领域
api, documentation

调研方向

从 src/Symfony/Bundle/DependencyInjection/Configuration.php 和 src/OpenApi/Factory/OpenApiFactory.php 开始,重点关注 getMimeTypes() 入口点。在确定范围之前,比较建议的 prefer_format、formats 和自动去重方案。完成的标准是:所选配置生成的 OpenAPI 输出只包含预期的 schema 和 content type,且不改变运行时格式。

由索引模型根据 Issue 内容生成。

描述

OpenAPI RFC

Context

When building a JSON-LD only API (no plain JSON format), the OpenAPI specification still generates duplicate schemas and content types. Users have to create custom OpenApiFactory decorators to filter these out.

Current Behavior

With this configuration:

api_platform:
    formats:
        jsonld: ['application/ld+json']
    error_formats:
        jsonld: ['application/ld+json']
        jsonproblem: ['application/problem+json']

The OpenAPI export still produces:

  1. Duplicate schemas: EmailMessage AND EmailMessage.jsonld
  2. Multiple content types in responses: application/ld+json, application/problem+json, application/json

Workaround We Implemented

We created an OpenApiFactory decorator that:

1. Filters non-JSON-LD content types from responses
private const NON_JSONLD_MIME_TYPES = [
    'text/html',
    'application/problem+json',
    'application/json',
];

private function filterNonJsonContentTypes(PathItem $pathItem): PathItem
{
    foreach (PathItem::$methods as $method) {
        $operation = $pathItem->{"get" . ucfirst(strtolower($method))}();
        if (null === $operation) continue;

        foreach ($operation->getResponses() as $status => $response) {
            $content = $response->getContent();
            if ($content) {
                $filteredContent = new \ArrayObject();
                foreach ($content as $mimeType => $mediaType) {
                    if (!in_array($mimeType, self::NON_JSONLD_MIME_TYPES, true)) {
                        $filteredContent[$mimeType] = $mediaType;
                    }
                }
                // ... update response
            }
        }
    }
    return $pathItem;
}
2. Removes duplicate schemas (keeps only .jsonld versions)
private function filterNonJsonSchemas(OpenApi $openApi): OpenApi
{
    $schemas = $openApi->getComponents()->getSchemas();

    // Collect base names that have .jsonld versions
    $jsonldSchemas = [];
    foreach ($schemas as $name => $schema) {
        if (str_ends_with($name, '.jsonld')) {
            $jsonldSchemas[substr($name, 0, -7)] = true;
        }
    }

    $filteredSchemas = new \ArrayObject();
    foreach ($schemas as $name => $schema) {
        $baseName = preg_replace('/\.jsonld$/', '', $name);

        // Skip non-.jsonld version when .jsonld exists
        if (!str_ends_with($name, '.jsonld') && isset($jsonldSchemas[$baseName])) {
            continue;
        }

        $filteredSchemas[$name] = $schema;
    }

    return $openApi->withComponents($components->withSchemas($filteredSchemas));
}

Proposed Framework Enhancement

Option A: openapi.prefer_format Configuration

Add a configuration option to specify the preferred format for OpenAPI documentation:

api_platform:
    openapi:
        prefer_format: jsonld  # Only show jsonld schemas and content types

Implementation:

In OpenApiFactory, when prefer_format is set:

  1. Only generate schemas for that format (skip others even if configured)
  2. Only include that format's content type in responses
  3. Remove duplicate schemas that exist in multiple format variants
Option B: openapi.formats Configuration

Allow explicit control over which formats appear in OpenAPI (separate from runtime formats):

api_platform:
    formats:
        jsonld: ['application/ld+json']
        json: ['application/json']  # Available at runtime
    openapi:
        formats:
            jsonld: ['application/ld+json']  # Only this in docs

Implementation:

In OpenApiFactory::getMimeTypes():

private function getMimeTypes(HttpOperation $operation): array
{
    // Use openapi.formats if configured, otherwise fall back to operation formats
    $responseFormats = $this->openapiFormats
        ?? $operation->getOutputFormats()
        ?? [];

    // ... rest of method
}
Option C: Automatic Deduplication

When multiple formats produce equivalent schemas (same structure, different naming), automatically deduplicate:

// In OpenApiFactory::collectPaths() or a new dedicated method
private function deduplicateSchemas(\ArrayObject $schemas): \ArrayObject
{
    $dominated = [];

    // jsonld dominates json (more specific)
    foreach ($schemas as $name => $schema) {
        if (str_ends_with($name, '.jsonld')) {
            $baseName = substr($name, 0, -7);
            if (isset($schemas[$baseName])) {
                $dominated[$baseName] = true;
            }
        }
    }

    // Remove dominated schemas
    foreach ($dominated as $name => $_) {
        unset($schemas[$name]);
    }

    return $schemas;
}

Recommendation

Option A (prefer_format) is the cleanest because:

  1. Simple, single configuration option
  2. Clear intent: "I want my OpenAPI docs in this format"
  3. Doesn't affect runtime behavior
  4. Easy to understand and document

Example implementation location:

  • Configuration: src/Symfony/Bundle/DependencyInjection/Configuration.php
  • Logic: src/OpenApi/Factory/OpenApiFactory.php

Additional Consideration: Accept/Content-Type Headers

Our decorator also adds Accept and Content-Type header parameters to all operations, showing available formats as an enum. This is useful documentation that API Platform could generate automatically.

parameters:
  - name: Accept
    in: header
    schema:
      type: string
      enum: ['application/ld+json']
      default: 'application/ld+json'

This could be another configuration option:

api_platform:
    openapi:
        document_content_negotiation_headers: true
主要语言
PHP
星标
2.6k
派生
987
平均合并
1 天 8 小时
30 天内合并 PR
80

环境准备

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

api-platform/core 的其他 Issue

查看 api-platform/core 的全部 Issue

相似的 Issue

更多 PHP Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。