Bug Report Checklist
Description
With library=microprofile, a property that is required and nullable via an OpenAPI
3.1 type array over a container type generates a field with an empty initializer:
private Map<String, Object> nullableMap = ;
private List<String> nullableArray = ;
javac then fails with illegal start of expression. Generation itself reports success,
so the failure only surfaces at compile time.
The trigger is required + type array containing "null" + a container type. Each part
matters:
| property |
generated |
ok |
required, type: [object, "null"] + additionalProperties |
Map<String, Object> x = ; |
✗ |
required, type: [array, "null"] + items |
List<String> x = ; |
✗ |
not required, type: [object, "null"] |
Map<String, Object> x = null; |
✓ |
required, plain type: object |
Map<String, Object> x = new HashMap<>(); |
✓ |
Cause
Java/libraries/microprofile/pojo.mustache interpolates defaultValue unguarded on the
required branch:
{{#isContainer}}
private {{{datatypeWithEnum}}} {{name}}{{#required}} = {{{defaultValue}}}{{/required}}{{^required}} = null{{/required}};
{{/isContainer}}
AbstractJavaCodegen.toDefaultValue returns Java null for a nullable container, which
is correct:
} else if (ModelUtils.isMapSchema(schema) && !(ModelUtils.isComposedSchema(schema))) {
...
// nullable or containerDefaultToNull set to true
if (cp.isNullable || containerDefaultToNull) {
return null;
}
{{{defaultValue}}} therefore renders as the empty string and leaves the bare =. The
{{^required}} branch hardcodes = null and so never hits this.
The generic Java/pojo.mustache guards the same interpolation with {{#defaultValue}},
which is why this is microprofile-only — okhttp-gson and native generate the spec
below correctly, with no initializer.
openapi-generator version
Reproduces on 7.13.0 and on 7.25.0. Not a regression as far as I can tell — the
unguarded interpolation is present in both.
Not affected by openApiNullable or containerDefaultToNull (tried both true and false),
nor by adding default: {} / default: null to the property, nor by expressing
nullability as anyOf/oneOf with type: "null".
OpenAPI declaration file
openapi: 3.1.0
info: {title: repro, version: "1.0.0"}
paths:
/thing:
get:
operationId: getThing
responses:
"200":
description: ok
content:
application/json:
schema: {$ref: "#/components/schemas/Thing"}
components:
schemas:
Thing:
type: object
properties:
nullableMap:
type: [object, "null"]
additionalProperties: true
nullableArray:
type: [array, "null"]
items: {type: string}
required: [nullableMap, nullableArray]
Command line used for generation
openapi-generator-cli generate -i spec.yaml -g java -o out \
--library microprofile \
--additional-properties microprofileRestClientVersion=3.0
Steps to reproduce
- Generate with the command above.
grep 'nullableMap' out/src/main/java/org/openapitools/client/model/Thing.java
- Observe
private Map<String, Object> nullableMap = ;
javac on the generated sources fails with illegal start of expression.
Swapping --library microprofile for native or omitting it (okhttp-gson) produces
compilable output for the same spec.
Suggested fix
Give the required branch the same fallback the non-required branch already has:
{{#isContainer}}
private {{{datatypeWithEnum}}} {{name}}{{#required}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{^defaultValue}} = null{{/defaultValue}}{{/required}}{{^required}} = null{{/required}};
{{/isContainer}}
Bug Report Checklist
Description
With
library=microprofile, a property that is required and nullable via an OpenAPI3.1 type array over a container type generates a field with an empty initializer:
javacthen fails withillegal start of expression. Generation itself reports success,so the failure only surfaces at compile time.
The trigger is
required+ type array containing"null"+ a container type. Each partmatters:
type: [object, "null"]+additionalPropertiesMap<String, Object> x = ;type: [array, "null"]+itemsList<String> x = ;type: [object, "null"]Map<String, Object> x = null;type: objectMap<String, Object> x = new HashMap<>();Cause
Java/libraries/microprofile/pojo.mustacheinterpolatesdefaultValueunguarded on therequired branch:
AbstractJavaCodegen.toDefaultValuereturns Javanullfor a nullable container, whichis correct:
{{{defaultValue}}}therefore renders as the empty string and leaves the bare=. The{{^required}}branch hardcodes= nulland so never hits this.The generic
Java/pojo.mustacheguards the same interpolation with{{#defaultValue}},which is why this is microprofile-only —
okhttp-gsonandnativegenerate the specbelow correctly, with no initializer.
openapi-generator version
Reproduces on 7.13.0 and on 7.25.0. Not a regression as far as I can tell — the
unguarded interpolation is present in both.
Not affected by
openApiNullableorcontainerDefaultToNull(tried both true and false),nor by adding
default: {}/default: nullto the property, nor by expressingnullability as
anyOf/oneOfwithtype: "null".OpenAPI declaration file
Command line used for generation
Steps to reproduce
grep 'nullableMap' out/src/main/java/org/openapitools/client/model/Thing.javaprivate Map<String, Object> nullableMap = ;javacon the generated sources fails withillegal start of expression.Swapping
--library microprofilefornativeor omitting it (okhttp-gson) producescompilable output for the same spec.
Suggested fix
Give the required branch the same fallback the non-required branch already has: