Skip to content

Commit a9d0883

Browse files
committed
1 parent 82d6263 commit a9d0883

3 files changed

Lines changed: 56 additions & 20 deletions

File tree

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@
2525
import io.swagger.v3.oas.models.media.Schema;
2626
import io.swagger.v3.oas.models.servers.Server;
2727
import io.swagger.v3.oas.models.tags.Tag;
28+
import lombok.Data;
2829
import lombok.Getter;
30+
import lombok.RequiredArgsConstructor;
2931
import lombok.Setter;
3032
import org.apache.commons.lang3.StringUtils;
3133
import org.apache.commons.lang3.tuple.Pair;
@@ -1147,6 +1149,29 @@ private Set<String> reformatProvideArgsParams(Operation operation) {
11471149
return provideArgsClassSet;
11481150
}
11491151

1152+
@Data
1153+
@RequiredArgsConstructor
1154+
static class ConstructorSpecs {
1155+
1156+
static final String JSON_CREATOR = "@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)";
1157+
private final String constructorAnnotation;
1158+
private final boolean useJsonProperty;
1159+
1160+
static ConstructorSpecs useJsonProperty(boolean useJsonProperty) {
1161+
return new ConstructorSpecs(useJsonProperty?JSON_CREATOR: null, useJsonProperty);
1162+
}
1163+
}
1164+
1165+
/**
1166+
* Is JSpecify used?
1167+
*
1168+
* TODO: make it configurable
1169+
*/
1170+
private boolean isUseJspecify() {
1171+
return importMapping.getOrDefault("Nullable", "")
1172+
.contains("jspecify");
1173+
}
1174+
11501175
@Override
11511176
public Map<String, ModelsMap> postProcessAllModels(Map<String, ModelsMap> objs) {
11521177
objs = super.postProcessAllModels(objs);
@@ -1156,26 +1181,35 @@ public Map<String, ModelsMap> postProcessAllModels(Map<String, ModelsMap> objs)
11561181
for (CodegenModel cm : allModels.values()) {
11571182
boolean hasLombokNoArgsConstructor = lombokAnnotations != null && lombokAnnotations.containsKey("NoArgsConstructor");
11581183
boolean hasAllArgsConstructor = cm.vendorExtensions.containsKey("x-java-all-args-constructor");
1184+
11591185
if (!hasLombokNoArgsConstructor
11601186
&& (cm.hasRequired || hasAllArgsConstructor)) {
1161-
cm.vendorExtensions.put("x-java-no-args-constructor", true);
1162-
}
11631187

1188+
String annotation = (cm.hasRequired && isUseJspecify())? "@org.jspecify.annotations.NullUnmarked": null;
11641189

1190+
ConstructorSpecs noArgSpec = new ConstructorSpecs(annotation, false);
1191+
cm.vendorExtensions.put("x-java-no-args-constructor", noArgSpec);
1192+
}
1193+
1194+
boolean requiredJsonProperty = false;
11651195
// add @JsonCreator on constructor
11661196
if (!this.withXml && jackson) {
11671197
if (hasAllArgsConstructor) {
11681198
// add @JsonCreator and @JsonProperty on the all argument constructor
1169-
cm.vendorExtensions.put("java-all-args-constructor-jsoncreator", true);
1170-
List<CodegenProperty> properties = (List<CodegenProperty>)cm.vendorExtensions.get("x-java-all-args-constructor-vars");
1171-
properties.forEach(p -> p.vendorExtensions.put("x-java-all-args-jsonProperty", p.baseName));
1199+
cm.vendorExtensions.put("x-java-all-args-constructor", ConstructorSpecs.useJsonProperty(true));
1200+
// List<CodegenProperty> properties = (List<CodegenProperty>)cm.vendorExtensions.get("x-java-all-args-constructor-vars");
1201+
// properties.forEach(p -> p.vendorExtensions.put("x-java-all-args-jsonProperty", p.baseName));
11721202
} else if (this.generatedConstructorWithRequiredArgs && cm.hasRequired && cm.requiredVars.size() == cm.allVars.size()) {
11731203
/* add @JsonCreator and @JsonProperty on the required argument constructor
11741204
* all fields are initialzed in the required constructor
11751205
* no all arg constructor
11761206
*/
1177-
cm.vendorExtensions.put("x-java-required-constructor-jsoncreator", true);
1178-
cm.requiredVars.forEach(p -> p.vendorExtensions.put("x-java-required-args-jsonProperty", p.baseName));
1207+
requiredJsonProperty = true;
1208+
// cm.vendorExtensions.put("x-java-required-constructor-jsoncreator", true);
1209+
// cm.requiredVars.forEach(p -> p.vendorExtensions.put("x-java-required-args-jsonProperty", p.baseName));
1210+
}
1211+
if (generatedConstructorWithRequiredArgs && cm.hasRequired) {
1212+
cm.vendorExtensions.put("x-java-required-args-constructor", ConstructorSpecs.useJsonProperty(requiredJsonProperty));
11791213
}
11801214
}
11811215

modules/openapi-generator/src/main/resources/JavaSpring/pojo.mustache

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -90,22 +90,24 @@ public {{>sealed}}class {{classname}}{{#parent}} extends {{{parent}}}{{/parent}}
9090
{{/vars}}
9191
{{#vendorExtensions.x-java-no-args-constructor}}
9292

93+
{{#constructorAnnotation}}
94+
{{.}}
95+
{{/constructorAnnotation}}
9396
public {{classname}}() {
9497
super();
9598
}
9699
{{/vendorExtensions.x-java-no-args-constructor}}
97100
{{^lombok.Data}}
98101
{{^lombok.RequiredArgsConstructor}}
99-
{{#generatedConstructorWithRequiredArgs}}
100-
{{#hasRequired}}
102+
{{#vendorExtensions.x-java-required-args-constructor}}
101103

102104
/**
103105
* Constructor with only required parameters{{#generateConstructorWithAllArgs}}{{^vendorExtensions.x-java-all-args-constructor}} and all parameters{{/vendorExtensions.x-java-all-args-constructor}}{{/generateConstructorWithAllArgs}}
104106
*/
105-
{{#vendorExtensions.x-java-required-constructor-jsoncreator}}
106-
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
107-
{{/vendorExtensions.x-java-required-constructor-jsoncreator}}
108-
public {{classname}}({{#requiredVars}}{{#vendorExtensions.x-java-required-args-jsonProperty}}@JsonProperty("{{.}}") {{/vendorExtensions.x-java-required-args-jsonProperty}}{{{datatypeWithEnum}}} {{name}}{{^-last}}, {{/-last}}{{/requiredVars}}) {
107+
{{#constructorAnnotation}}
108+
{{.}}
109+
{{/constructorAnnotation}}
110+
public {{classname}}({{#requiredVars}}{{#useJsonProperty}}@JsonProperty("{{baseName}}") {{/useJsonProperty}}{{{datatypeWithEnum}}} {{name}}{{^-last}}, {{/-last}}{{/requiredVars}}) {
109111
{{#parent}}
110112
super({{#parentRequiredVars}}{{name}}{{^-last}}, {{/-last}}{{/parentRequiredVars}});
111113
{{/parent}}
@@ -120,18 +122,17 @@ public {{>sealed}}class {{classname}}{{#parent}} extends {{{parent}}}{{/parent}}
120122
{{/required}}
121123
{{/vars}}
122124
}
123-
{{/hasRequired}}
124-
{{/generatedConstructorWithRequiredArgs}}
125+
{{/vendorExtensions.x-java-required-args-constructor}}
125126
{{/lombok.RequiredArgsConstructor}}
126127
{{#vendorExtensions.x-java-all-args-constructor}}
127128

128129
/**
129130
* Constructor with all args parameters
130131
*/
131-
{{#vendorExtensions.java-all-args-constructor-jsoncreator}}
132-
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
133-
{{/vendorExtensions.java-all-args-constructor-jsoncreator}}
134-
public {{classname}}({{#vendorExtensions.x-java-all-args-constructor-vars}}{{#vendorExtensions.x-java-all-args-jsonProperty}}@JsonProperty("{{.}}") {{/vendorExtensions.x-java-all-args-jsonProperty}}{{>nullableAnnotation}}{{{datatypeWithEnum}}} {{name}}{{^-last}}, {{/-last}}{{/vendorExtensions.x-java-all-args-constructor-vars}}) {
132+
{{#constructorAnnotation}}
133+
{{.}}
134+
{{/constructorAnnotation}}
135+
public {{classname}}({{#vendorExtensions.x-java-all-args-constructor-vars}}{{#useJsonProperty}}@JsonProperty("{{baseName}}") {{/useJsonProperty}}{{>nullableAnnotation}}{{{datatypeWithEnum}}} {{name}}{{^-last}}, {{/-last}}{{/vendorExtensions.x-java-all-args-constructor-vars}}) {
135136
{{#parent}}
136137
super({{#parentVars}}{{name}}{{^-last}}, {{/-last}}{{/parentVars}});
137138
{{/parent}}

modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4905,7 +4905,8 @@ public void testAllArgsConstructor_defaultOrder_15796() throws IOException {
49054905
public void generateAllArgsConstructor() throws IOException {
49064906
Map<String, File> files = generateFromContract("src/test/resources/3_0/java/all_args_constructor.yaml", null,
49074907
Map.of(AbstractJavaCodegen.GENERATE_CONSTRUCTOR_WITH_ALL_ARGS, Boolean.TRUE, INTERFACE_ONLY, "true"),
4908-
codegenConfig -> codegenConfig.addOpenapiNormalizer("REFACTOR_ALLOF_WITH_PROPERTIES_ONLY", " true"));
4908+
codegenConfig -> codegenConfig.addOpenapiNormalizer("REFACTOR_ALLOF_WITH_PROPERTIES_ONLY", " true")
4909+
.setImportMappings(Map.of("Nullable", "org.jspecify.annotations.Nullable")));
49094910
JavaFileAssert.assertThat(files.get("Pet.java"))
49104911
.assertConstructor("String")
49114912
.hasParameter("type").toConstructor()

0 commit comments

Comments
 (0)