From a00549cd65ae3fcb7f759164284a5ae7be20c6f4 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Thu, 25 Apr 2024 12:52:48 +0800 Subject: [PATCH] Add an option to skip unmarshall json in Go client generator (#18448) * feat(go): Add a vendor extension to option out of generating the UnmarshalJSON method * add generate unmarshal json option in go client generator * update doc --------- Co-authored-by: Radoslav Kotsev --- docs/generators/go.md | 1 + .../codegen/CodegenConstants.java | 2 + .../codegen/languages/AbstractGoCodegen.java | 12 +++- .../codegen/languages/GoClientCodegen.java | 6 ++ .../main/resources/go/model_simple.mustache | 2 + .../codegen/go/GoClientCodegenTest.java | 42 ++++++++++++++ .../codegen/go/GoClientOptionsTest.java | 1 + .../options/GoClientOptionsProvider.java | 2 + .../3_0/go/allof_skip_unmarshal_json.yaml | 55 +++++++++++++++++++ .../3_0/go/allof_with_unmarshal_json.yaml | 54 ++++++++++++++++++ 10 files changed, 176 insertions(+), 1 deletion(-) create mode 100644 modules/openapi-generator/src/test/resources/3_0/go/allof_skip_unmarshal_json.yaml create mode 100644 modules/openapi-generator/src/test/resources/3_0/go/allof_with_unmarshal_json.yaml diff --git a/docs/generators/go.md b/docs/generators/go.md index 31dae23e98..e81de548e9 100644 --- a/docs/generators/go.md +++ b/docs/generators/go.md @@ -22,6 +22,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |enumClassPrefix|Prefix enum with class name| |false| |generateInterfaces|Generate interfaces for api classes| |false| |generateMarshalJSON|Generate MarshalJSON method| |true| +|generateUnmarshalJSON|Generate UnmarshalJSON method| |true| |hideGenerationTimestamp|Hides the generation timestamp when files are generated.| |true| |isGoSubmodule|whether the generated Go module is a submodule| |false| |packageName|Go package name (convention: lowercase).| |openapi| diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java index 84920eacfd..017bf79406 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java @@ -442,6 +442,8 @@ public class CodegenConstants { public static final String GENERATE_MARSHAL_JSON = "generateMarshalJSON"; public static final String GENERATE_MARSHAL_JSON_DESC = "Generate MarshalJSON method"; + public static final String GENERATE_UNMARSHAL_JSON = "generateUnmarshalJSON"; + public static final String GENERATE_UNMARSHAL_JSON_DESC = "Generate UnmarshalJSON method"; public static final String MAX_ATTEMPTS_FOR_RETRY = "maxAttemptsForRetry"; public static final String WAIT_TIME_OF_THREAD = "waitTimeMillis"; diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractGoCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractGoCodegen.java index a64c09e0a4..ed02f152fa 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractGoCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractGoCodegen.java @@ -48,6 +48,8 @@ public abstract class AbstractGoCodegen extends DefaultCodegen implements Codege protected boolean generateInterfaces = false; protected boolean withGoMod = false; protected boolean generateMarshalJSON = true; + protected boolean generateUnmarshalJSON = true; + protected String packageName = "openapi"; protected Set numberTypes; @@ -775,7 +777,11 @@ public abstract class AbstractGoCodegen extends DefaultCodegen implements Codege } if (generateMarshalJSON) { - model.vendorExtensions.put("x-go-generate-marshal-json", true); + model.vendorExtensions.putIfAbsent("x-go-generate-marshal-json", true); + } + + if (generateUnmarshalJSON) { + model.vendorExtensions.putIfAbsent("x-go-generate-unmarshal-json", true); } } @@ -932,6 +938,10 @@ public abstract class AbstractGoCodegen extends DefaultCodegen implements Codege this.generateMarshalJSON = generateMarshalJSON; } + public void setGenerateUnmarshalJSON(boolean generateUnmarshalJSON) { + this.generateUnmarshalJSON = generateUnmarshalJSON; + } + @Override public String toDefaultValue(Schema schema) { schema = unaliasSchema(schema); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoClientCodegen.java index f079b45078..060dfc277d 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoClientCodegen.java @@ -150,6 +150,7 @@ public class GoClientCodegen extends AbstractGoCodegen { this.setDisallowAdditionalPropertiesIfNotPresent(true); cliOptions.add(CliOption.newBoolean(WITH_GO_MOD, "Generate go.mod and go.sum", true)); cliOptions.add(CliOption.newBoolean(CodegenConstants.GENERATE_MARSHAL_JSON, CodegenConstants.GENERATE_MARSHAL_JSON_DESC, true)); + cliOptions.add(CliOption.newBoolean(CodegenConstants.GENERATE_UNMARSHAL_JSON, CodegenConstants.GENERATE_UNMARSHAL_JSON_DESC, true)); this.setWithGoMod(true); } @@ -287,6 +288,11 @@ public class GoClientCodegen extends AbstractGoCodegen { setGenerateMarshalJSON(Boolean.parseBoolean(additionalProperties.get(CodegenConstants.GENERATE_MARSHAL_JSON).toString())); } + if (additionalProperties.containsKey(CodegenConstants.GENERATE_UNMARSHAL_JSON)) { + setGenerateUnmarshalJSON(Boolean.parseBoolean(additionalProperties.get(CodegenConstants.GENERATE_UNMARSHAL_JSON).toString())); + } + + // add lambda for mustache templates to handle oneOf/anyOf naming // e.g. []string => ArrayOfString additionalProperties.put("lambda.type-to-name", (Mustache.Lambda) (fragment, writer) -> writer.write(typeToName(fragment.execute()))); diff --git a/modules/openapi-generator/src/main/resources/go/model_simple.mustache b/modules/openapi-generator/src/main/resources/go/model_simple.mustache index 48c6a81c23..cf9ecac947 100644 --- a/modules/openapi-generator/src/main/resources/go/model_simple.mustache +++ b/modules/openapi-generator/src/main/resources/go/model_simple.mustache @@ -337,6 +337,7 @@ func (o {{classname}}) ToMap() (map[string]interface{}, error) { return toSerialize, nil } +{{#vendorExtensions.x-go-generate-unmarshal-json}} {{#isAdditionalPropertiesTrue}} func (o *{{{classname}}}) UnmarshalJSON(data []byte) (err error) { {{/isAdditionalPropertiesTrue}} @@ -514,4 +515,5 @@ func (o *{{{classname}}}) UnmarshalJSON(data []byte) (err error) { } {{/isArray}} +{{/vendorExtensions.x-go-generate-unmarshal-json}} {{>nullable_model}} diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/go/GoClientCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/go/GoClientCodegenTest.java index b8fcfdcdc7..188cba014f 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/go/GoClientCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/go/GoClientCodegenTest.java @@ -312,6 +312,48 @@ public class GoClientCodegenTest { "BaseItem"); } + @Test + public void testVendorExtensionGenerateUnmarshalJson() throws IOException { + File output = Files.createTempDirectory("test").toFile(); + output.deleteOnExit(); + + final CodegenConfigurator configurator = new CodegenConfigurator() + .setGeneratorName("go") + .setGitUserId("OpenAPITools") + .setGitRepoId("openapi-generator") + .setInputSpec("src/test/resources/3_0/go/allof_with_unmarshal_json.yaml") + .setOutputDir(output.getAbsolutePath().replace("\\", "/")); + + DefaultGenerator generator = new DefaultGenerator(); + List files = generator.opts(configurator.toClientOptInput()).generate(); + files.forEach(File::deleteOnExit); + + TestUtils.assertFileExists(Paths.get(output + "/model_base_item.go")); + TestUtils.assertFileContains(Paths.get(output + "/model_base_item.go"), + "func (o *BaseItem) UnmarshalJSON(data []byte) (err error) {"); + } + + @Test + public void testVendorExtensionSkipGenerateUnmarshalJson() throws IOException { + File output = Files.createTempDirectory("test").toFile(); + output.deleteOnExit(); + + final CodegenConfigurator configurator = new CodegenConfigurator() + .setGeneratorName("go") + .setGitUserId("OpenAPITools") + .setGitRepoId("openapi-generator") + .setInputSpec("src/test/resources/3_0/go/allof_skip_unmarshal_json.yaml") + .setOutputDir(output.getAbsolutePath().replace("\\", "/")); + + DefaultGenerator generator = new DefaultGenerator(); + List files = generator.opts(configurator.toClientOptInput()).generate(); + files.forEach(File::deleteOnExit); + + TestUtils.assertFileExists(Paths.get(output + "/model_base_item.go")); + TestUtils.assertFileNotContains(Paths.get(output + "/model_base_item.go"), + "func (o *BaseItem) UnmarshalJSON(data []byte) (err error) {"); + } + @Test public void testAdditionalPropertiesWithGoMod() throws Exception { File output = Files.createTempDirectory("test").toFile(); diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/go/GoClientOptionsTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/go/GoClientOptionsTest.java index 8a67ee0e68..603515e7e9 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/go/GoClientOptionsTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/go/GoClientOptionsTest.java @@ -53,5 +53,6 @@ public class GoClientOptionsTest extends AbstractOptionsTest { verify(clientCodegen).setUseOneOfDiscriminatorLookup(GoClientOptionsProvider.USE_ONE_OF_DISCRIMINATOR_LOOKUP_VALUE); verify(clientCodegen).setWithGoMod(GoClientOptionsProvider.WITH_GO_MOD_VALUE); verify(clientCodegen).setGenerateMarshalJSON(GoClientOptionsProvider.GENERATE_MARSHAL_JSON_VALUE); + verify(clientCodegen).setGenerateUnmarshalJSON(GoClientOptionsProvider.GENERATE_UNMARSHAL_JSON_VALUE); } } diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/GoClientOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/GoClientOptionsProvider.java index 830fd29a6c..372e293f63 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/GoClientOptionsProvider.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/GoClientOptionsProvider.java @@ -38,6 +38,7 @@ public class GoClientOptionsProvider implements OptionsProvider { public static final boolean USE_ONE_OF_DISCRIMINATOR_LOOKUP_VALUE = true; public static final boolean WITH_GO_MOD_VALUE = true; public static final boolean GENERATE_MARSHAL_JSON_VALUE = true; + public static final boolean GENERATE_UNMARSHAL_JSON_VALUE = true; @Override public String getLanguage() { @@ -60,6 +61,7 @@ public class GoClientOptionsProvider implements OptionsProvider { .put(CodegenConstants.USE_ONEOF_DISCRIMINATOR_LOOKUP, "true") .put(CodegenConstants.WITH_GO_MOD, "true") .put(CodegenConstants.GENERATE_MARSHAL_JSON, "true") + .put(CodegenConstants.GENERATE_UNMARSHAL_JSON, "true") .put("generateInterfaces", "true") .put("structPrefix", "true") .build(); diff --git a/modules/openapi-generator/src/test/resources/3_0/go/allof_skip_unmarshal_json.yaml b/modules/openapi-generator/src/test/resources/3_0/go/allof_skip_unmarshal_json.yaml new file mode 100644 index 0000000000..bd69102a85 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/go/allof_skip_unmarshal_json.yaml @@ -0,0 +1,55 @@ +openapi: 3.0.0 +info: + title: Test + version: 1.0.0 +paths: {} +components: + schemas: + FinalItem: + type: object + allOf: + - $ref: '#/components/schemas/BaseItem' + - $ref: '#/components/schemas/AdditionalData' + BaseItem: + type: object + x-go-generate-unmarshal-json: false + properties: + title: + type: string + type: + type: string + enum: + - FINAL + example: FINAL + discriminator: + propertyName: type + mapping: + FINAL: '#/components/schemas/FinalItem' + required: + - title + - type + AdditionalData: + type: object + properties: + prop1: + type: string + quantity: + type: integer + format: int32 + example: 1 + minimum: 1 + unitPrice: + type: number + format: double + example: 9.99 + minimum: 0.0 + totalPrice: + type: number + format: double + example: 9.99 + minimum: 0.0 + required: + - prop1 + - quantity + - unitPrice + - totalPrice \ No newline at end of file diff --git a/modules/openapi-generator/src/test/resources/3_0/go/allof_with_unmarshal_json.yaml b/modules/openapi-generator/src/test/resources/3_0/go/allof_with_unmarshal_json.yaml new file mode 100644 index 0000000000..f32b662de1 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/go/allof_with_unmarshal_json.yaml @@ -0,0 +1,54 @@ +openapi: 3.0.0 +info: + title: Test + version: 1.0.0 +paths: {} +components: + schemas: + FinalItem: + type: object + allOf: + - $ref: '#/components/schemas/BaseItem' + - $ref: '#/components/schemas/AdditionalData' + BaseItem: + type: object + properties: + title: + type: string + type: + type: string + enum: + - FINAL + example: FINAL + discriminator: + propertyName: type + mapping: + FINAL: '#/components/schemas/FinalItem' + required: + - title + - type + AdditionalData: + type: object + properties: + prop1: + type: string + quantity: + type: integer + format: int32 + example: 1 + minimum: 1 + unitPrice: + type: number + format: double + example: 9.99 + minimum: 0.0 + totalPrice: + type: number + format: double + example: 9.99 + minimum: 0.0 + required: + - prop1 + - quantity + - unitPrice + - totalPrice \ No newline at end of file