Repository navigation
Description
Bug Report Checklist
- Have you provided a full/minimal spec to reproduce the issue?
- Have you validated the input using an OpenAPI validator? (
openapi-generator-cli validate: "No validation issues detected.") - Have you tested with the latest master to confirm the issue still exists? (
7.27.0-SNAPSHOT, commit 3faf172) - Have you searched for related issues/PRs? (see below)
- What's the actual output vs expected output?
- [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description
When all the schemas mapped by a oneOf discriminator declare the discriminator property as a $ref to the same primitive alias schema (here ShapeKind: a plain type: string schema without enum), the generated oneOf interface declares the getter with the name of the alias schema (ShapeKind getKind()). No model is generated for a primitive alias, and the implementing classes correctly use String, so the generated code does not compile (cannot find symbol).
7.25.0 generates String getKind(). This looks like a side effect of #24812: when only one distinct property schema remains and it is a $ref, DefaultCodegen#getCommonSchemaType returns toModelName(<ref>) without checking that a model exists for it.
Affected generators (tested): spring (with default options), jaxrs-spec and java (--library restclient / resttemplate) with useOneOfInterfaces=true. Not affected (tested with default options): kotlin, kotlin-spring.
openapi-generator version
7.26.0. It is a regression: 7.25.0 is fine. Still reproducible with the latest snapshot (7.27.0-SNAPSHOT, commit 3faf172).
OpenAPI declaration file content or url
shapes.yaml
openapi: 3.0.3
info:
title: Discriminator property typed by a primitive alias
version: 1.0.0
paths:
/shape:
get:
operationId: getShape
responses:
'200':
description: A shape
content:
application/json:
schema:
$ref: '#/components/schemas/Shape'
components:
schemas:
Shape:
oneOf:
- $ref: '#/components/schemas/Circle'
- $ref: '#/components/schemas/Square'
discriminator:
propertyName: kind
mapping:
circle: '#/components/schemas/Circle'
square: '#/components/schemas/Square'
ShapeKind:
type: string
description: The kind of shape.
Circle:
type: object
required:
- kind
properties:
kind:
$ref: '#/components/schemas/ShapeKind'
radius:
type: number
Square:
type: object
required:
- kind
properties:
kind:
$ref: '#/components/schemas/ShapeKind'
side:
type: numberGeneration Details
java -jar openapi-generator-cli-7.26.0.jar generate -g spring -i shapes.yaml -o out --global-property modelsNo additional options are needed (JDK 21). The same happens with -g jaxrs-spec --additional-properties useOneOfInterfaces=true or -g java --library restclient --additional-properties useOneOfInterfaces=true.
Steps to reproduce
-
Generate as above with 7.26.0 (and with 7.25.0 for comparison).
-
Look at
out/src/main/java/org/openapitools/model/Shape.java.7.25.0:
public interface Shape { public String getKind(); }
7.26.0:
public interface Shape { public ShapeKind getKind(); }
There is no
ShapeKind.java(onlyShape,CircleandSquareare generated), andCircle/SquareuseString getKind(). -
Compiling the generated sources fails:
org/openapitools/model/Shape.java:37: error: cannot find symbol public ShapeKind getKind(); ^ symbol: class ShapeKind location: interface Shape
Observations that narrow the cause:
- It only happens when the discriminator property resolves to exactly one distinct schema across all the mapped subtypes. If each subtype references its own alias schema, the output is fine (
String getKind()): that goes through the multi-schema branch ofgetCommonSchemaType, which dereferences the$refs first. - It also happens when the alias property is inherited through
allOffrom a shared base schema. - An integer alias (
type: integer) or aformat: uuidalias fails the same way.
Related issues/PRs
- fix(core) handle mismatching discriminatorType in oneOf interfaces #24812 (merged 2026-09-06): introduced
getCommonSchemaType/DiscriminatorUtils.getDistinctTypes. "Matching$reftypes are used" assumes that a model exists for every$ref. - [BUG] [JAVA] Broken code generation when using
format: enum#24950 / fix(java): do not map 'format: enum' schemas to 'Enum' #25008: another regression from the same change (format: enummapped toEnum), different trigger. - [REQ] [Java] Allow excluding discriminator property from generated models #24769, [BUG][Spring] code generation fails if oneOf discriminator is enum #19194, [BUG][Java] useOneOfInterfaces generates incompatible discriminator return types for inline enums #24959: the non-
Stringdiscriminator problems that fix(core) handle mismatching discriminatorType in oneOf interfaces #24812 fixes. The fix suggested below keeps that behavior. - [Java] Fix oneOf discriminator type for inline schemas and allOf inheritance #24156 (open): also touches discriminator type resolution, possibly overlapping.
I could not find an existing issue or PR about discriminators typed by a primitive alias.
Suggest a fix
In DefaultCodegen#getCommonSchemaType (case 1), when the only distinct property schema is a $ref, resolve aliases of primitive types first before treating the $ref as a model name. This mirrors getSingleSchemaType, which computes the property type of the implementing classes: unaliasSchema, then the model name if a $ref remains, otherwise the primitive type:
Schema first = schemas.get(0);
try {
if (StringUtils.isNotEmpty(first.get$ref())) {
+ // a $ref to an alias of a primitive type has no model: use the aliased type,
+ // like the type of the property in the concrete models
+ first = unaliasSchema(first);
+ }
+ if (StringUtils.isNotEmpty(first.get$ref())) {
return toModelName(ModelUtils.getSimpleRef(first.get$ref()));
}unaliasSchema keeps the $ref for everything that gets a generated model (enums, objects, composed schemas, schemaMappings targets), so the existing behavior for those is unchanged. Primitive aliases (also alias of alias) are resolved to the underlying schema and handled like an inline property (String, Integer, UUID, ...), consistent with the implementing classes. It does not touch the lines changed by #25008.
Validation of the patch (patched DefaultCodegen, compiled against the 7.26.0 jar; the file is identical on master):
- The reproduction above generates
String getKind()forspring,jaxrs-specandjava(restclient,resttemplate); the generatedspringandrestclientmodel sources compile with javac. - A spec with six oneOf groups compiles with javac: integer alias ->
Integer,format: uuidalias ->UUID, alias of an alias ->String, alias of an enum -> the enum model, direct$refto an enum -> the enum model (unchanged from 7.26.0), inline string ->String. For comparison, the same spec gives 16 compile errors with 7.25.0 (non-Stringdiscriminators, the problem fixed by fix(core) handle mismatching discriminatorType in oneOf interfaces #24812) and 4 with 7.26.0 (the alias groups). - Generating the 150 test specs that mention
discriminator(modules/openapi-generator/src/test/resources/3_0and3_1) withspringand withjava --library restclient(both withuseOneOfInterfaces=true) gives byte-identical output with and without the patch. None of them exercises a primitive-alias discriminator, so a regression test would be new coverage.
Happy to open a PR with the change and a regression test if this approach looks right.
Activity