Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

OpenAPI: Non-JSON formats should not generate JSON schemas

Open
#7,802 5 comments 1 reaction 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
45/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Stale
Tech stack
openapi, php
Domain
api

Research direction

Start in src/OpenApi/Factory/OpenApiFactory.php and src/Symfony/Bundle/Resources/config/openapi.php, then inspect how jsonschema_formats is computed in ApiPlatformExtension.php. Update the OpenAPI behavior for non-JSON response formats and add the regression case in tests/OpenApi/Factory/OpenApiFactoryTest.php; done means non-JSON formats no longer receive generated JSON schemas.

Written by the indexing model from the issue text.

Description

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.

Dominant language
PHP
Stars
2.6k
Forks
989
Avg merge
1d 22h
Merged PRs (30d)
100

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from api-platform/core

All issues in api-platform/core

Similar issues

More PHP issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.