Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -173,36 +173,84 @@ public class {{classname}} {{#parent}}extends {{{.}}}{{/parent}} {{#vendorExtens

{{#isArray}}
public {{classname}} add{{nameInPascalCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) {
{{#vendorExtensions.x-is-jackson-optional-nullable}}
if (this.{{name}} == null || !this.{{name}}.isPresent() || this.{{name}}.get() == null) {
this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}{{^defaultValue}}new {{#uniqueItems}}LinkedHashSet{{/uniqueItems}}{{^uniqueItems}}ArrayList{{/uniqueItems}}<>(){{/defaultValue}});
}
try {
this.{{name}}.get().add({{name}}Item);
} catch (java.util.NoSuchElementException e) {
// this can never happen, as we make sure above that the value is present
}
return this;
{{/vendorExtensions.x-is-jackson-optional-nullable}}
{{^vendorExtensions.x-is-jackson-optional-nullable}}
if (this.{{name}} == null) {
this.{{name}} = {{{defaultValue}}}{{^defaultValue}}new {{#uniqueItems}}LinkedHashSet{{/uniqueItems}}{{^uniqueItems}}ArrayList{{/uniqueItems}}<>(){{/defaultValue}};
}

this.{{name}}.add({{name}}Item);
return this;
{{/vendorExtensions.x-is-jackson-optional-nullable}}
}

public {{classname}} remove{{nameInPascalCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) {
{{#vendorExtensions.x-is-jackson-optional-nullable}}
if ({{name}}Item != null && this.{{name}} != null && this.{{name}}.isPresent()) {
try {
this.{{name}}.get().remove({{name}}Item);
} catch (java.util.NoSuchElementException e) {
// this can never happen, as we make sure above that the value is present
}
}
{{/vendorExtensions.x-is-jackson-optional-nullable}}
{{^vendorExtensions.x-is-jackson-optional-nullable}}
if ({{name}}Item != null && this.{{name}} != null) {
this.{{name}}.remove({{name}}Item);
}
{{/vendorExtensions.x-is-jackson-optional-nullable}}

return this;
}
{{/isArray}}
{{#isMap}}
public {{classname}} put{{nameInPascalCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) {
{{#vendorExtensions.x-is-jackson-optional-nullable}}
if (this.{{name}} == null || !this.{{name}}.isPresent() || this.{{name}}.get() == null) {
this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}{{^defaultValue}}new HashMap<>(){{/defaultValue}});
}
try {
this.{{name}}.get().put(key, {{name}}Item);
} catch (java.util.NoSuchElementException e) {
// this can never happen, as we make sure above that the value is present
}
return this;
{{/vendorExtensions.x-is-jackson-optional-nullable}}
{{^vendorExtensions.x-is-jackson-optional-nullable}}
if (this.{{name}} == null) {
this.{{name}} = {{{defaultValue}}}{{^defaultValue}}new HashMap<>(){{/defaultValue}};
}

this.{{name}}.put(key, {{name}}Item);
return this;
{{/vendorExtensions.x-is-jackson-optional-nullable}}
}

public {{classname}} remove{{nameInPascalCase}}Item(String key) {
{{#vendorExtensions.x-is-jackson-optional-nullable}}
if (this.{{name}} != null && this.{{name}}.isPresent()) {
try {
this.{{name}}.get().remove(key);
} catch (java.util.NoSuchElementException e) {
// this can never happen, as we make sure above that the value is present
}
}
{{/vendorExtensions.x-is-jackson-optional-nullable}}
{{^vendorExtensions.x-is-jackson-optional-nullable}}
if (this.{{name}} != null) {
this.{{name}}.remove(key);
}
{{/vendorExtensions.x-is-jackson-optional-nullable}}

return this;
}
Expand Down Expand Up @@ -283,4 +331,4 @@ public class {{classname}} {{#parent}}extends {{{.}}}{{/parent}} {{#vendorExtens
}
{{/vars}}
}{{/additionalProperties}}{{/generateBuilders}}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1236,5 +1236,43 @@ public void disableGenerateJsonCreator() throws Exception {

assertFileNotContains(files.get("RequiredProperties.java").toPath(), "@JsonCreator");
}

@Test
public void testGenerateJsonNullableListFieldsHelperMethodReferences_issue23251() throws Exception {
Map<String, Object> properties = new HashMap<>();
properties.put(OPENAPI_NULLABLE, "true");

File output = Files.createTempDirectory("test").toFile();

final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("jaxrs-spec")
.setAdditionalProperties(properties)
.setInputSpec("src/test/resources/bugs/issue_23251.yaml")
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));

final ClientOptInput clientOptInput = configurator.toClientOptInput();
DefaultGenerator generator = new DefaultGenerator();
List<File> files = generator.opts(clientOptInput).generate();

validateJavaSourceFiles(files);

TestUtils.ensureContainsFile(files, output, "src/gen/java/org/openapitools/model/BugResponse.java");

// Assert that the generated model contains JsonNullable fields
assertFileContains(output.toPath().resolve("src/gen/java/org/openapitools/model/BugResponse.java"),
"private JsonNullable<String> nullableField = JsonNullable.<String>undefined();",
"private JsonNullable<List<String>> nullableList = JsonNullable.<List<String>>undefined();",
"private JsonNullable<List<@Valid NestedResponse>> nullableObjectList = JsonNullable.<List<@Valid NestedResponse>>undefined();"
);

// Assert that the generated model contains correct add and remove helper methods reference for JsonNullable fields
assertFileContains(output.toPath().resolve("src/gen/java/org/openapitools/model/BugResponse.java"),
"this.nullableList.get().add(nullableListItem);",
"this.nullableList.get().remove(nullableListItem);",
"this.nullableObjectList.get().add(nullableObjectListItem);",
"this.nullableObjectList.get().remove(nullableObjectListItem);");

output.deleteOnExit();
}

}
44 changes: 44 additions & 0 deletions modules/openapi-generator/src/test/resources/bugs/issue_23251.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
openapi: 3.0.2
info:
title: Reproduce
version: 1.0.0
paths:
/test:
get:
summary: test
operationId: test
responses:
200:
description: Test
content:
application/json:
schema:
$ref: '#/components/schemas/BugResponse'
components:
schemas:
BugResponse:
type: object
properties:
nullableField:
type: string
nullable: true
x-is-jackson-optional-nullable: true
nullableList:
type: array
items:
type: string
nullable: true
x-is-jackson-optional-nullable: true
nullableObjectList:
type: array
items:
$ref: '#/components/schemas/NestedResponse'
nullable: true
x-is-jackson-optional-nullable: true
NestedResponse:
type: object
properties:
nestedField:
type: string
nullable: true
x-is-jackson-optional-nullable: true