Skip to content

Commit

Permalink
[JAVA] Fix jackson (de)serializer annotation breaking libs using gson…
Browse files Browse the repository at this point in the history
… when `bigDecimalAsString=true` (OpenAPITools#18835)

* Implement regression test for bigDecimalAsString annotations

* Ensure @JsonSerialize and @JsonDeserialize is only generated when Jackson enabled

Fixes OpenAPITools#6496
  • Loading branch information
Philzen authored and welshm committed Jun 5, 2024
1 parent 3c98216 commit a106437
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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)");
Expand All @@ -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)");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.*;
Expand Down Expand Up @@ -2610,6 +2611,62 @@ private void testHandleURIEnum(String library, String[] expectedInnerEnumLines,
);
}

/**
* Regression test for <a href="https://github.com/OpenAPITools/openapi-generator/issues/6496">#6496</a>
*/
@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<File> 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 <a href="https://github.com/OpenAPITools/openapi-generator/issues/6496">#6496</a> 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<File> 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");
Expand Down
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit a106437

Please sign in to comment.