diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java index 0ca8bcc2b360..08e55928f655 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java @@ -1779,7 +1779,7 @@ private void addAdditionalImports(CodegenModel model, CodegenComposedSchemas com @Override public void postProcessModelProperty(CodegenModel model, CodegenProperty property) { - if (serializeBigDecimalAsString) { + if (serializeBigDecimalAsString && additionalProperties.containsKey(JACKSON)) { if ("decimal".equals(property.baseType) || "bigdecimal".equalsIgnoreCase(property.baseType)) { // we serialize BigDecimal as `string` to avoid precision loss property.vendorExtensions.put("x-extra-annotation", "@JsonSerialize(using = ToStringSerializer.class)"); @@ -1804,7 +1804,7 @@ public void postProcessModelProperty(CodegenModel model, CodegenProperty propert model.imports.add("Arrays"); } else if ("set".equals(property.containerType)) { model.imports.add("LinkedHashSet"); - if (!openApiNullable || !property.isNullable) { // cannot be wrapped to nullable + if ((!openApiNullable || !property.isNullable) && additionalProperties.containsKey(JACKSON)) { // cannot be wrapped to nullable model.imports.add("JsonDeserialize"); property.vendorExtensions.put("x-setter-extra-annotation", "@JsonDeserialize(as = LinkedHashSet.class)"); } diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java index 878e9358a02a..49410305d19a 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java @@ -58,6 +58,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; +import static org.assertj.core.api.InstanceOfAssertFactories.FILE; import static org.openapitools.codegen.CodegenConstants.SERIALIZATION_LIBRARY; import static org.openapitools.codegen.TestUtils.validateJavaSourceFiles; import static org.openapitools.codegen.languages.JavaClientCodegen.*; @@ -2610,6 +2611,62 @@ private void testHandleURIEnum(String library, String[] expectedInnerEnumLines, ); } + /** + * Regression test for #6496 + */ + @Test void doesNotGenerateJacksonToStringSerializerAnnotation_whenLibraryIsGson_andSerializeBigDecimalAsStringIsTrue() { + final CodegenConfigurator configurator = new CodegenConfigurator() + .setGeneratorName("java") + .setLibrary(JavaClientCodegen.OKHTTP_GSON) + .addAdditionalProperty(CodegenConstants.SERIALIZATION_LIBRARY, SERIALIZATION_LIBRARY_GSON) + .addAdditionalProperty(CodegenConstants.SERIALIZE_BIG_DECIMAL_AS_STRING, true) + .addGlobalProperty(CodegenConstants.MODELS, "FormatTest") + .addGlobalProperty(CodegenConstants.MODEL_DOCS, "false") + .addGlobalProperty(CodegenConstants.MODEL_TESTS, "false") + .setInputSpec("src/test/resources/2_0/java/issue-6496.yaml") + .setOutputDir(newTempFolder().toString().replace("\\", "/")); + + List files = new DefaultGenerator().opts(configurator.toClientOptInput()).generate(); + + assertThat(files).hasSize(1).first(FILE).content() + .doesNotContain( + "@JsonDeserialize(as = LinkedHashSet.class)", + "@JsonSerialize(using = ToStringSerializer.class)", + "com.fasterxml.jackson.databind.ser.std.ToStringSerializer", + "com.fasterxml.jackson.databind.annotation.JsonDeserialize", + "com.fasterxml.jackson.databind.annotation.JsonSerialize" + ); + } + + /** + * Test that fix for #6496 has + * no unwanted side effects on the existing feature (Jackson + bigDecimalAsString) + */ + @Test void generatesJacksonToStringSerializerAnnotation_whenLibraryIsJackson_andSerializeBigDecimalAsStringIsTrue() { + final CodegenConfigurator configurator = new CodegenConfigurator() + .setGeneratorName("java") + .setLibrary(JavaClientCodegen.NATIVE) + .addAdditionalProperty(CodegenConstants.SERIALIZATION_LIBRARY, SERIALIZATION_LIBRARY_JACKSON) + .addAdditionalProperty(CodegenConstants.SERIALIZE_BIG_DECIMAL_AS_STRING, true) + .addAdditionalProperty(OPENAPI_NULLABLE, false) + .addGlobalProperty(CodegenConstants.MODELS, "FormatTest") + .addGlobalProperty(CodegenConstants.MODEL_DOCS, "false") + .addGlobalProperty(CodegenConstants.MODEL_TESTS, "false") + .setInputSpec("src/test/resources/2_0/java/issue-6496.yaml") + .setOutputDir(newTempFolder().toString().replace("\\", "/")); + + List files = new DefaultGenerator().opts(configurator.toClientOptInput()).generate(); + + assertThat(files).hasSize(1).first(FILE).content() + .contains( + "@JsonDeserialize(as = LinkedHashSet.class)", + "@JsonSerialize(using = ToStringSerializer.class)", + "com.fasterxml.jackson.databind.ser.std.ToStringSerializer", + "com.fasterxml.jackson.databind.annotation.JsonDeserialize", + "com.fasterxml.jackson.databind.annotation.JsonSerialize" + ); + } + static private Path newTempFolder() { try { var tempDir = Files.createTempDirectory("test"); diff --git a/modules/openapi-generator/src/test/resources/2_0/java/issue-6496.yaml b/modules/openapi-generator/src/test/resources/2_0/java/issue-6496.yaml new file mode 100644 index 000000000000..17ddfae04563 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/2_0/java/issue-6496.yaml @@ -0,0 +1,88 @@ +swagger: '2.0' +info: + description: "This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\" + version: 1.0.0 + title: OpenAPI Petstore + license: + name: Apache-2.0 + url: 'https://www.apache.org/licenses/LICENSE-2.0.html' +basePath: /v2 +schemes: + - http +paths: + /: + get: + operationId: addPet + responses: + '200': + description: successful operation +definitions: + FormatTest: + type: object + required: + - number + - byte + - date + - password + properties: + integer: + type: integer + maximum: 100 + minimum: 10 + int32: + type: integer + format: int32 + maximum: 200 + minimum: 20 + int64: + type: integer + format: int64 + number: + maximum: 543.2 + minimum: 32.1 + type: number + float: + type: number + format: float + maximum: 987.6 + minimum: 54.3 + double: + type: number + format: double + maximum: 123.4 + minimum: 67.8 + string: + type: string + pattern: /[a-z]/i + byte: + type: string + format: byte + binary: + type: string + format: binary + date: + type: string + format: date + dateTime: + type: string + format: date-time + uuid: + type: string + format: uuid + example: 72f98069-206d-4f12-9f12-3d1e525a8e84 + password: + type: string + format: password + maxLength: 64 + minLength: 10 + BigDecimal: + type: string + format: number + enumContainer: + type: array + uniqueItems: true + items: + enum: + - placed + - approved + - delivered