[BUG][JAVA][SPRING] Fix serialization when there is a discriminator with mapping (#14733) (fix #14731)

* Fix serialization when there is a discriminator with mapping

* Update samples

* Update samples

* upgrade samples

* Revert "Update samples"

This reverts commit d6affde263d6c539e32a7f38dc984cf5948ab322.
This commit is contained in:
Jorge Rodríguez Martín 2023-02-18 16:00:44 +01:00 committed by GitHub
parent c5d67ee042
commit cb20e742ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 274 additions and 4 deletions

View File

@ -15,7 +15,9 @@
{{/vars}} {{/vars}}
}) })
{{#isClassnameSanitized}} {{#isClassnameSanitized}}
{{^hasDiscriminatorWithNonEmptyMapping}}
@JsonTypeName("{{name}}") @JsonTypeName("{{name}}")
{{/hasDiscriminatorWithNonEmptyMapping}}
{{/isClassnameSanitized}} {{/isClassnameSanitized}}
{{/jackson}} {{/jackson}}
{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}} {{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}}

View File

@ -15,7 +15,9 @@
{{/discriminator}} {{/discriminator}}
{{#jackson}} {{#jackson}}
{{#isClassnameSanitized}} {{#isClassnameSanitized}}
{{^hasDiscriminatorWithNonEmptyMapping}}
@JsonTypeName("{{name}}") @JsonTypeName("{{name}}")
{{/hasDiscriminatorWithNonEmptyMapping}}
{{/isClassnameSanitized}} {{/isClassnameSanitized}}
{{/jackson}} {{/jackson}}
{{#withXml}} {{#withXml}}

View File

@ -18,6 +18,7 @@
package org.openapitools.codegen.java; package org.openapitools.codegen.java;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import io.swagger.parser.OpenAPIParser;
import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.media.ArraySchema; import io.swagger.v3.oas.models.media.ArraySchema;
@ -30,6 +31,7 @@ import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.media.StringSchema; import io.swagger.v3.oas.models.media.StringSchema;
import io.swagger.v3.oas.models.parameters.RequestBody; import io.swagger.v3.oas.models.parameters.RequestBody;
import io.swagger.v3.oas.models.responses.ApiResponse; import io.swagger.v3.oas.models.responses.ApiResponse;
import io.swagger.v3.parser.core.models.ParseOptions;
import io.swagger.v3.parser.util.SchemaTypeUtil; import io.swagger.v3.parser.util.SchemaTypeUtil;
import org.openapitools.codegen.ClientOptInput; import org.openapitools.codegen.ClientOptInput;
import org.openapitools.codegen.CodegenConstants; import org.openapitools.codegen.CodegenConstants;
@ -75,6 +77,8 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static org.openapitools.codegen.TestUtils.assertFileContains;
import static org.openapitools.codegen.TestUtils.assertFileNotContains;
import static org.openapitools.codegen.TestUtils.validateJavaSourceFiles; import static org.openapitools.codegen.TestUtils.validateJavaSourceFiles;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue; import static org.testng.Assert.assertTrue;
@ -1752,4 +1756,82 @@ public class JavaClientCodegenTest {
TestUtils.assertFileContains(Paths.get(output + "/src/main/java/xyz/abcdef/model/AnotherChild.java"), TestUtils.assertFileContains(Paths.get(output + "/src/main/java/xyz/abcdef/model/AnotherChild.java"),
"public class AnotherChild {"); "public class AnotherChild {");
} }
@Test
public void testDiscriminatorWithMappingIssue14731() throws IOException {
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
output.deleteOnExit();
String outputPath = output.getAbsolutePath().replace('\\', '/');
OpenAPI openAPI = new OpenAPIParser()
.readLocation("src/test/resources/bugs/issue_14731.yaml", null, new ParseOptions()).getOpenAPI();
JavaClientCodegen codegen = new JavaClientCodegen();
codegen.setOutputDir(output.getAbsolutePath());
codegen.additionalProperties().put(CXFServerFeatures.LOAD_TEST_DATA_FROM_FILE, "true");
codegen.setUseOneOfInterfaces(true);
ClientOptInput input = new ClientOptInput();
input.openAPI(openAPI);
input.config(codegen);
DefaultGenerator generator = new DefaultGenerator();
generator.setGeneratorPropertyDefault(CodegenConstants.MODELS, "true");
generator.setGeneratorPropertyDefault(CodegenConstants.LEGACY_DISCRIMINATOR_BEHAVIOR, "false");
codegen.setUseOneOfInterfaces(true);
codegen.setLegacyDiscriminatorBehavior(false);
codegen.setUseJakartaEe(true);
codegen.setModelNameSuffix("DTO");
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_TESTS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_DOCS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.APIS, "true");
generator.setGeneratorPropertyDefault(CodegenConstants.SUPPORTING_FILES, "false");
generator.opts(input).generate();
assertFileNotContains(Paths.get(outputPath + "/src/main/java/org/openapitools/client/model/ChildWithMappingADTO.java"), "@JsonTypeName");
assertFileNotContains(Paths.get(outputPath + "/src/main/java/org/openapitools/client/model/ChildWithMappingBDTO.java"), "@JsonTypeName");
}
@Test
public void testDiscriminatorWithoutMappingIssue14731() throws IOException {
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
output.deleteOnExit();
String outputPath = output.getAbsolutePath().replace('\\', '/');
OpenAPI openAPI = new OpenAPIParser()
.readLocation("src/test/resources/bugs/issue_14731.yaml", null, new ParseOptions()).getOpenAPI();
JavaClientCodegen codegen = new JavaClientCodegen();
codegen.setOutputDir(output.getAbsolutePath());
codegen.additionalProperties().put(CXFServerFeatures.LOAD_TEST_DATA_FROM_FILE, "true");
codegen.setUseOneOfInterfaces(true);
ClientOptInput input = new ClientOptInput();
input.openAPI(openAPI);
input.config(codegen);
DefaultGenerator generator = new DefaultGenerator();
generator.setGeneratorPropertyDefault(CodegenConstants.MODELS, "true");
generator.setGeneratorPropertyDefault(CodegenConstants.LEGACY_DISCRIMINATOR_BEHAVIOR, "false");
codegen.setUseOneOfInterfaces(true);
codegen.setLegacyDiscriminatorBehavior(false);
codegen.setUseJakartaEe(true);
codegen.setModelNameSuffix("DTO");
codegen.setLibrary(JavaClientCodegen.RESTTEMPLATE);
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_TESTS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_DOCS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.APIS, "true");
generator.setGeneratorPropertyDefault(CodegenConstants.SUPPORTING_FILES, "false");
generator.opts(input).generate();
assertFileContains(Paths.get(outputPath + "/src/main/java/org/openapitools/client/model/ChildWithoutMappingADTO.java"), "@JsonTypeName");
assertFileContains(Paths.get(outputPath + "/src/main/java/org/openapitools/client/model/ChildWithoutMappingBDTO.java"), "@JsonTypeName");
}
} }

View File

@ -1141,6 +1141,85 @@ public class SpringCodegenTest {
assertFileContains(Paths.get(outputPath + "/src/main/java/org/openapitools/model/PizzaSpeziale.java"), "import java.math.BigDecimal"); assertFileContains(Paths.get(outputPath + "/src/main/java/org/openapitools/model/PizzaSpeziale.java"), "import java.math.BigDecimal");
} }
@Test
public void testDiscriminatorWithMappingIssue14731() throws IOException {
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
output.deleteOnExit();
String outputPath = output.getAbsolutePath().replace('\\', '/');
OpenAPI openAPI = new OpenAPIParser()
.readLocation("src/test/resources/bugs/issue_14731.yaml", null, new ParseOptions()).getOpenAPI();
SpringCodegen codegen = new SpringCodegen();
codegen.setOutputDir(output.getAbsolutePath());
codegen.additionalProperties().put(CXFServerFeatures.LOAD_TEST_DATA_FROM_FILE, "true");
codegen.setUseOneOfInterfaces(true);
ClientOptInput input = new ClientOptInput();
input.openAPI(openAPI);
input.config(codegen);
DefaultGenerator generator = new DefaultGenerator();
codegen.setHateoas(true);
generator.setGeneratorPropertyDefault(CodegenConstants.MODELS, "true");
generator.setGeneratorPropertyDefault(CodegenConstants.LEGACY_DISCRIMINATOR_BEHAVIOR, "false");
codegen.setUseOneOfInterfaces(true);
codegen.setLegacyDiscriminatorBehavior(false);
codegen.setUseSpringBoot3(true);
codegen.setModelNameSuffix("DTO");
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_TESTS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_DOCS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.APIS, "true");
generator.setGeneratorPropertyDefault(CodegenConstants.SUPPORTING_FILES, "false");
generator.opts(input).generate();
assertFileNotContains(Paths.get(outputPath + "/src/main/java/org/openapitools/model/ChildWithMappingADTO.java"), "@JsonTypeName");
assertFileNotContains(Paths.get(outputPath + "/src/main/java/org/openapitools/model/ChildWithMappingBDTO.java"), "@JsonTypeName");
}
@Test
public void testDiscriminatorWithoutMappingIssue14731() throws IOException {
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
output.deleteOnExit();
String outputPath = output.getAbsolutePath().replace('\\', '/');
OpenAPI openAPI = new OpenAPIParser()
.readLocation("src/test/resources/bugs/issue_14731.yaml", null, new ParseOptions()).getOpenAPI();
SpringCodegen codegen = new SpringCodegen();
codegen.setOutputDir(output.getAbsolutePath());
codegen.additionalProperties().put(CXFServerFeatures.LOAD_TEST_DATA_FROM_FILE, "true");
codegen.setUseOneOfInterfaces(true);
ClientOptInput input = new ClientOptInput();
input.openAPI(openAPI);
input.config(codegen);
DefaultGenerator generator = new DefaultGenerator();
codegen.setHateoas(true);
generator.setGeneratorPropertyDefault(CodegenConstants.MODELS, "true");
generator.setGeneratorPropertyDefault(CodegenConstants.LEGACY_DISCRIMINATOR_BEHAVIOR, "false");
codegen.setUseOneOfInterfaces(true);
codegen.setLegacyDiscriminatorBehavior(false);
codegen.setUseSpringBoot3(true);
codegen.setModelNameSuffix("DTO");
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_TESTS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_DOCS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.APIS, "true");
generator.setGeneratorPropertyDefault(CodegenConstants.SUPPORTING_FILES, "false");
generator.opts(input).generate();
assertFileContains(Paths.get(outputPath + "/src/main/java/org/openapitools/model/ChildWithoutMappingADTO.java"), "@JsonTypeName");
assertFileContains(Paths.get(outputPath + "/src/main/java/org/openapitools/model/ChildWithoutMappingBDTO.java"), "@JsonTypeName");
}
@Test @Test
public void testTypeMappings() { public void testTypeMappings() {
final SpringCodegen codegen = new SpringCodegen(); final SpringCodegen codegen = new SpringCodegen();

View File

@ -0,0 +1,109 @@
openapi: '3.0.0'
info:
version: '1.0.0'
title: 'FooService'
paths:
/parentWithMapping:
put:
tags:
- pet
summary: put parent
operationId: putParentWithMapping
requestBody:
description: The updated account definition to save.
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ParentWithMapping'
responses:
'200':
$ref: '#/components/responses/ParentWithMapping'
/parentWithoutMapping:
put:
tags:
- pet
summary: put parent
operationId: putParentWithoutMapping
requestBody:
description: The updated account definition to save.
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ParentWithoutMapping'
responses:
'200':
$ref: '#/components/responses/ParentWithoutMapping'
components:
schemas:
ParentWithMapping:
type: object
description: Defines an account by name.
properties:
childType:
$ref: '#/components/schemas/ChildType'
required:
- type
discriminator:
propertyName: childType
mapping:
child_a: '#/components/schemas/ChildWithMappingA'
child_b: '#/components/schemas/ChildWithMappingB'
ChildWithMappingA:
allOf:
- $ref: "#/components/schemas/ParentWithMapping"
- type: object
properties:
nameA:
type: string
ChildWithMappingB:
allOf:
- $ref: "#/components/schemas/ParentWithMapping"
- type: object
properties:
nameB:
type: string
ChildType:
type: string
x-extensible-enum:
- child_a
- child_b
ParentWithoutMapping:
type: object
description: Defines an account by name.
properties:
childType:
$ref: '#/components/schemas/ChildType'
required:
- type
discriminator:
propertyName: childType
ChildWithoutMappingA:
allOf:
- $ref: "#/components/schemas/ParentWithoutMapping"
- type: object
properties:
nameA:
type: string
ChildWithoutMappingB:
allOf:
- $ref: "#/components/schemas/ParentWithoutMapping"
- type: object
properties:
nameB:
type: string
responses:
ParentWithMapping:
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/ParentWithMapping'
ParentWithoutMapping:
description: The saved account definition.
content:
application/json:
schema:
$ref: '#/components/schemas/ParentWithoutMapping'

View File

@ -34,7 +34,6 @@ import jakarta.annotation.Generated;
@JsonSubTypes.Type(value = DogDto.class, name = "Dog") @JsonSubTypes.Type(value = DogDto.class, name = "Dog")
}) })
@JsonTypeName("Animal")
@Generated(value = "org.openapitools.codegen.languages.SpringCodegen") @Generated(value = "org.openapitools.codegen.languages.SpringCodegen")
public class AnimalDto { public class AnimalDto {

View File

@ -31,7 +31,6 @@ import jakarta.annotation.Generated;
@JsonSubTypes.Type(value = BigCatDto.class, name = "BigCat") @JsonSubTypes.Type(value = BigCatDto.class, name = "BigCat")
}) })
@JsonTypeName("Cat")
@Generated(value = "org.openapitools.codegen.languages.SpringCodegen") @Generated(value = "org.openapitools.codegen.languages.SpringCodegen")
public class CatDto extends AnimalDto { public class CatDto extends AnimalDto {

View File

@ -37,7 +37,6 @@ import javax.annotation.Generated;
@JsonSubTypes.Type(value = DogDto.class, name = "Dog") @JsonSubTypes.Type(value = DogDto.class, name = "Dog")
}) })
@JsonTypeName("Animal")
@Generated(value = "org.openapitools.codegen.languages.SpringCodegen") @Generated(value = "org.openapitools.codegen.languages.SpringCodegen")
public class AnimalDto { public class AnimalDto {

View File

@ -34,7 +34,6 @@ import javax.annotation.Generated;
@JsonSubTypes.Type(value = BigCatDto.class, name = "BigCat") @JsonSubTypes.Type(value = BigCatDto.class, name = "BigCat")
}) })
@JsonTypeName("Cat")
@Generated(value = "org.openapitools.codegen.languages.SpringCodegen") @Generated(value = "org.openapitools.codegen.languages.SpringCodegen")
public class CatDto extends AnimalDto { public class CatDto extends AnimalDto {