OpenAPITools / OpenAPITools/openapi-generator
[BUG][jaxrs-spec] Discriminated model serializes a duplicate `type` with the class name instead of the discriminator value
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 26.8k
- Forks
- 7.7k
- PR merge metrics
- PR metrics pending
Description
Bug Report Checklist
- Have you provided a full/minimal spec to reproduce the issue?
- Have you validated the input using an OpenAPI validator (example)?
- Have you tested with the latest master to confirm the issue still exists?
Description
For a discriminated polymorphic model (oneOf-by-inheritance via allOf + discriminator.mapping), the jaxrs-spec generator produces Java that serializes a duplicate discriminator property with the wrong value.
The generated base class is annotated:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type", visible = true)
and each concrete subtype gets:
@JsonTypeName("TrackMessage") // <-- the CLASS NAME, not the discriminator value "track"
Because visible = true keeps type as a real bean property and the type id is emitted from @JsonTypeName (the class name), serializing a subtype yields a duplicate key:
{"type":"TrackMessage","type":"track", ...}
Deserialization is correct (it uses the @JsonSubTypes name = "track" mapping); only serialization is broken.
This is not fixable from the spec: x-discriminator-value (at the child schema top level or inside the allOf member), removing the type property, and removing the discriminator mapping all fail to change @JsonTypeName/visible. Removing the mapping additionally breaks reads (@JsonSubTypes then uses the class name).
openapi-generator version
Reproduced on 7.7.0, 7.11.0, and 7.14.0 (identical output).
OpenAPI declaration file content or url
openapi: 3.1.0
info: { title: repro, version: 1.0.0 }
paths: {}
components:
schemas:
MessageType:
type: string
enum: [track, page]
AnyMessage:
type: object
required: [type]
properties:
type: { $ref: '#/components/schemas/MessageType' }
messageId: { type: string }
discriminator:
propertyName: type
mapping:
track: '#/components/schemas/TrackMessage'
page: '#/components/schemas/PageMessage'
TrackMessage:
allOf:
- $ref: '#/components/schemas/AnyMessage'
- type: object
required: [event]
properties:
event: { type: string }
PageMessage:
allOf:
- $ref: '#/components/schemas/AnyMessage'
- type: object
properties:
name: { type: string }
Generation command
openapi-generator-cli generate -g jaxrs-spec -i repro.yaml -o out \
-p interfaceOnly=true,useJakartaEe=true,useBeanValidation=true,dateLibrary=java8
Steps to reproduce
- Generate with the command above.
- Inspect
AnyMessage.java→@JsonTypeInfo(..., property = "type", visible = true). - Inspect
TrackMessage.java→@JsonTypeName("TrackMessage")(class name, nottrack). new ObjectMapper().writeValueAsString(trackMessage)→{"type":"TrackMessage","type":"track", ...}.
Expected
Serializing a TrackMessage should emit a single, correct discriminator: {"type":"track", ...}. @JsonTypeName should be the discriminator value from the mapping (track), and the generator should not emit type twice (either visible = false, or suppress the redundant bean property on write).
Related issues/PRs
Searched open issues; none found matching this jaxrs-spec discriminator-serialization case.
Suggested fix
Either set @JsonTypeName to the discriminator value derived from discriminator.mapping (currently the schema/class name), or avoid double-emitting the discriminator when visible = true and a same-named bean property exists.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Run the supplied openapi-generator-cli command with repro.yaml, then inspect AnyMessage.java and TrackMessage.java for the emitted @JsonTypeInfo and @JsonTypeName annotations. Trace the jaxrs-spec generator path that produces them; done means TrackMessage serialization emits one type property with value track while deserialization remains correct.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, openapi
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 58/100