Skip to content

fix(openapi): serialize Reference objects with $ref in the generated document#8306

Merged
soyuka merged 2 commits into
api-platform:4.3from
soyuka:fix/openapi-ref-8143
Jun 16, 2026
Merged

fix(openapi): serialize Reference objects with $ref in the generated document#8306
soyuka merged 2 commits into
api-platform:4.3from
soyuka:fix/openapi-ref-8143

Conversation

@soyuka

@soyuka soyuka commented Jun 16, 2026

Copy link
Copy Markdown
Member

Summary

A custom OpenApiFactory placing a Reference object in Operation::$responses produced "ref" instead of "$ref" in the generated OpenAPI document. The dedicated inline ObjectNormalizer used by OpenApiNormalizer was constructed without a class metadata factory or a metadata-aware name converter, so Reference::getRef()'s #[SerializedName('$ref')] was never applied. Reference::$ref is the only #[SerializedName] among the OpenAPI models, so the change only affects this property — emitting the spec-correct $ref.

Reproduction

Serializing an OpenAPI document whose components/responses reference a schema via a Reference object emitted the key as ref, which is invalid per the OpenAPI spec.

Test plan

  • Added failing unit test (OpenApiNormalizerTest) and functional test (OpenApiTest, real DI) asserting $ref is present.
  • Both pass after the fix.
  • Existing OpenAPI normalizer/serializer suites stay green (27 tests, 259 assertions).

Note: a pre-existing, unrelated failure in OpenApiFactoryTest::testInvoke (a 422 response description default) exists on 4.3 HEAD independently of this change.

Fixes #8143

soyuka added 2 commits June 16, 2026 10:55
…document

The openapi serializer's inline ObjectNormalizer was built without a class
metadata factory or a metadata-aware name converter, so Reference::getRef()'s
#[SerializedName('$ref')] was ignored and emitted as "ref". Wire the standard
class_metadata_factory and metadata-aware name converter so the model's own
serialization metadata is honored.

Fixes api-platform#8143
The Issue8143 ReferenceResponse fixture emits a $ref to
#/components/responses/401, but the generated document defined no such
component, so the Redocly no-unresolved-refs rule failed. Register a test-only
OpenApiFactory decorator that declares the reusable 401 response component so
the $ref resolves, without weakening the assertion that $ref is emitted.
@soyuka soyuka merged commit 553f6d3 into api-platform:4.3 Jun 16, 2026
109 of 112 checks passed
@thomas-hiron

Copy link
Copy Markdown
Contributor

Hi! I think there is a regression with this.
My config is the following:

framework:
    serializer:
        name_converter: serializer.name_converter.camel_case_to_snake_case

api_platform:
    path_segment_name_generator: api_platform.metadata.path_segment_name_generator.dash
    name_converter: serializer.name_converter.camel_case_to_snake_case

And now, the spec is generated in snake_case: operation_id, extension_properties...
And openapi-generator-cli doesn't support extension_properties:

-attribute paths.'/api/article'(get).extension_properties is unexpected

How to configure the spec being generated in camel case? Should I open an issue?

Thanks!

@soyuka

soyuka commented Jun 27, 2026

Copy link
Copy Markdown
Member Author

@thomas-hiron confirmed, this is a regression — not a config issue on your side. #8306 wired serializer.name_converter.metadata_aware into the OpenAPI serializer to honor #[SerializedName('$ref')], but that service carries your framework.serializer.name_converter as its fallback, so the global camelCase_to_snake_case converter leaked into the whole document (operation_id, extension_properties, …).

Fix in #8360: a dedicated MetadataAwareNameConverter with no fallback — $ref is still honored, the global converter no longer applies. No config change needed on your end.

soyuka added a commit to soyuka/core that referenced this pull request Jun 29, 2026
…document

PR api-platform#8306 wired serializer.name_converter.metadata_aware into the OpenAPI
serializer to honor #[SerializedName('$ref')] on Reference. That service
carries framework.serializer.name_converter as its fallback, so a globally
configured converter (e.g. camelCase_to_snake_case) leaked into the spec,
producing keys like operation_id, extension_properties, request_bodies that
break openapi-generator-cli.

Use a dedicated MetadataAwareNameConverter with no fallback: SerializedName
metadata is still honored, the global converter no longer applies.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants