Skip to content

Commit cb20e74

Browse files
authored
[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 d6affde.
1 parent c5d67ee commit cb20e74

9 files changed

Lines changed: 274 additions & 4 deletions

File tree

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
{{/vars}}
1616
})
1717
{{#isClassnameSanitized}}
18+
{{^hasDiscriminatorWithNonEmptyMapping}}
1819
@JsonTypeName("{{name}}")
20+
{{/hasDiscriminatorWithNonEmptyMapping}}
1921
{{/isClassnameSanitized}}
2022
{{/jackson}}
2123
{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
{{/discriminator}}
1616
{{#jackson}}
1717
{{#isClassnameSanitized}}
18+
{{^hasDiscriminatorWithNonEmptyMapping}}
1819
@JsonTypeName("{{name}}")
20+
{{/hasDiscriminatorWithNonEmptyMapping}}
1921
{{/isClassnameSanitized}}
2022
{{/jackson}}
2123
{{#withXml}}

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

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
package org.openapitools.codegen.java;
1919

2020
import com.google.common.collect.ImmutableMap;
21+
import io.swagger.parser.OpenAPIParser;
2122
import io.swagger.v3.oas.models.OpenAPI;
2223
import io.swagger.v3.oas.models.Operation;
2324
import io.swagger.v3.oas.models.media.ArraySchema;
@@ -30,6 +31,7 @@
3031
import io.swagger.v3.oas.models.media.StringSchema;
3132
import io.swagger.v3.oas.models.parameters.RequestBody;
3233
import io.swagger.v3.oas.models.responses.ApiResponse;
34+
import io.swagger.v3.parser.core.models.ParseOptions;
3335
import io.swagger.v3.parser.util.SchemaTypeUtil;
3436
import org.openapitools.codegen.ClientOptInput;
3537
import org.openapitools.codegen.CodegenConstants;
@@ -75,6 +77,8 @@
7577
import java.util.regex.Pattern;
7678
import java.util.stream.Collectors;
7779

80+
import static org.openapitools.codegen.TestUtils.assertFileContains;
81+
import static org.openapitools.codegen.TestUtils.assertFileNotContains;
7882
import static org.openapitools.codegen.TestUtils.validateJavaSourceFiles;
7983
import static org.testng.Assert.assertEquals;
8084
import static org.testng.Assert.assertTrue;
@@ -1752,4 +1756,82 @@ public void testJdkHttpClientWithAndWithoutParentExtension() throws Exception {
17521756
TestUtils.assertFileContains(Paths.get(output + "/src/main/java/xyz/abcdef/model/AnotherChild.java"),
17531757
"public class AnotherChild {");
17541758
}
1759+
1760+
@Test
1761+
public void testDiscriminatorWithMappingIssue14731() throws IOException {
1762+
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
1763+
output.deleteOnExit();
1764+
String outputPath = output.getAbsolutePath().replace('\\', '/');
1765+
OpenAPI openAPI = new OpenAPIParser()
1766+
.readLocation("src/test/resources/bugs/issue_14731.yaml", null, new ParseOptions()).getOpenAPI();
1767+
1768+
JavaClientCodegen codegen = new JavaClientCodegen();
1769+
codegen.setOutputDir(output.getAbsolutePath());
1770+
codegen.additionalProperties().put(CXFServerFeatures.LOAD_TEST_DATA_FROM_FILE, "true");
1771+
codegen.setUseOneOfInterfaces(true);
1772+
1773+
ClientOptInput input = new ClientOptInput();
1774+
input.openAPI(openAPI);
1775+
input.config(codegen);
1776+
1777+
DefaultGenerator generator = new DefaultGenerator();
1778+
generator.setGeneratorPropertyDefault(CodegenConstants.MODELS, "true");
1779+
generator.setGeneratorPropertyDefault(CodegenConstants.LEGACY_DISCRIMINATOR_BEHAVIOR, "false");
1780+
1781+
1782+
codegen.setUseOneOfInterfaces(true);
1783+
codegen.setLegacyDiscriminatorBehavior(false);
1784+
codegen.setUseJakartaEe(true);
1785+
codegen.setModelNameSuffix("DTO");
1786+
1787+
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_TESTS, "false");
1788+
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_DOCS, "false");
1789+
generator.setGeneratorPropertyDefault(CodegenConstants.APIS, "true");
1790+
generator.setGeneratorPropertyDefault(CodegenConstants.SUPPORTING_FILES, "false");
1791+
1792+
generator.opts(input).generate();
1793+
1794+
assertFileNotContains(Paths.get(outputPath + "/src/main/java/org/openapitools/client/model/ChildWithMappingADTO.java"), "@JsonTypeName");
1795+
assertFileNotContains(Paths.get(outputPath + "/src/main/java/org/openapitools/client/model/ChildWithMappingBDTO.java"), "@JsonTypeName");
1796+
}
1797+
1798+
@Test
1799+
public void testDiscriminatorWithoutMappingIssue14731() throws IOException {
1800+
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
1801+
output.deleteOnExit();
1802+
String outputPath = output.getAbsolutePath().replace('\\', '/');
1803+
OpenAPI openAPI = new OpenAPIParser()
1804+
.readLocation("src/test/resources/bugs/issue_14731.yaml", null, new ParseOptions()).getOpenAPI();
1805+
1806+
JavaClientCodegen codegen = new JavaClientCodegen();
1807+
codegen.setOutputDir(output.getAbsolutePath());
1808+
codegen.additionalProperties().put(CXFServerFeatures.LOAD_TEST_DATA_FROM_FILE, "true");
1809+
codegen.setUseOneOfInterfaces(true);
1810+
1811+
ClientOptInput input = new ClientOptInput();
1812+
input.openAPI(openAPI);
1813+
input.config(codegen);
1814+
1815+
DefaultGenerator generator = new DefaultGenerator();
1816+
generator.setGeneratorPropertyDefault(CodegenConstants.MODELS, "true");
1817+
generator.setGeneratorPropertyDefault(CodegenConstants.LEGACY_DISCRIMINATOR_BEHAVIOR, "false");
1818+
1819+
1820+
codegen.setUseOneOfInterfaces(true);
1821+
codegen.setLegacyDiscriminatorBehavior(false);
1822+
codegen.setUseJakartaEe(true);
1823+
codegen.setModelNameSuffix("DTO");
1824+
codegen.setLibrary(JavaClientCodegen.RESTTEMPLATE);
1825+
1826+
1827+
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_TESTS, "false");
1828+
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_DOCS, "false");
1829+
generator.setGeneratorPropertyDefault(CodegenConstants.APIS, "true");
1830+
generator.setGeneratorPropertyDefault(CodegenConstants.SUPPORTING_FILES, "false");
1831+
1832+
generator.opts(input).generate();
1833+
1834+
assertFileContains(Paths.get(outputPath + "/src/main/java/org/openapitools/client/model/ChildWithoutMappingADTO.java"), "@JsonTypeName");
1835+
assertFileContains(Paths.get(outputPath + "/src/main/java/org/openapitools/client/model/ChildWithoutMappingBDTO.java"), "@JsonTypeName");
1836+
}
17551837
}

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

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1141,6 +1141,85 @@ public void testOneOfAndAllOf() throws IOException {
11411141
assertFileContains(Paths.get(outputPath + "/src/main/java/org/openapitools/model/PizzaSpeziale.java"), "import java.math.BigDecimal");
11421142
}
11431143

1144+
@Test
1145+
public void testDiscriminatorWithMappingIssue14731() throws IOException {
1146+
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
1147+
output.deleteOnExit();
1148+
String outputPath = output.getAbsolutePath().replace('\\', '/');
1149+
OpenAPI openAPI = new OpenAPIParser()
1150+
.readLocation("src/test/resources/bugs/issue_14731.yaml", null, new ParseOptions()).getOpenAPI();
1151+
1152+
SpringCodegen codegen = new SpringCodegen();
1153+
codegen.setOutputDir(output.getAbsolutePath());
1154+
codegen.additionalProperties().put(CXFServerFeatures.LOAD_TEST_DATA_FROM_FILE, "true");
1155+
codegen.setUseOneOfInterfaces(true);
1156+
1157+
ClientOptInput input = new ClientOptInput();
1158+
input.openAPI(openAPI);
1159+
input.config(codegen);
1160+
1161+
DefaultGenerator generator = new DefaultGenerator();
1162+
codegen.setHateoas(true);
1163+
generator.setGeneratorPropertyDefault(CodegenConstants.MODELS, "true");
1164+
generator.setGeneratorPropertyDefault(CodegenConstants.LEGACY_DISCRIMINATOR_BEHAVIOR, "false");
1165+
1166+
1167+
codegen.setUseOneOfInterfaces(true);
1168+
codegen.setLegacyDiscriminatorBehavior(false);
1169+
codegen.setUseSpringBoot3(true);
1170+
codegen.setModelNameSuffix("DTO");
1171+
1172+
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_TESTS, "false");
1173+
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_DOCS, "false");
1174+
generator.setGeneratorPropertyDefault(CodegenConstants.APIS, "true");
1175+
generator.setGeneratorPropertyDefault(CodegenConstants.SUPPORTING_FILES, "false");
1176+
1177+
generator.opts(input).generate();
1178+
1179+
assertFileNotContains(Paths.get(outputPath + "/src/main/java/org/openapitools/model/ChildWithMappingADTO.java"), "@JsonTypeName");
1180+
assertFileNotContains(Paths.get(outputPath + "/src/main/java/org/openapitools/model/ChildWithMappingBDTO.java"), "@JsonTypeName");
1181+
}
1182+
1183+
@Test
1184+
public void testDiscriminatorWithoutMappingIssue14731() throws IOException {
1185+
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
1186+
output.deleteOnExit();
1187+
String outputPath = output.getAbsolutePath().replace('\\', '/');
1188+
OpenAPI openAPI = new OpenAPIParser()
1189+
.readLocation("src/test/resources/bugs/issue_14731.yaml", null, new ParseOptions()).getOpenAPI();
1190+
1191+
SpringCodegen codegen = new SpringCodegen();
1192+
codegen.setOutputDir(output.getAbsolutePath());
1193+
codegen.additionalProperties().put(CXFServerFeatures.LOAD_TEST_DATA_FROM_FILE, "true");
1194+
codegen.setUseOneOfInterfaces(true);
1195+
1196+
ClientOptInput input = new ClientOptInput();
1197+
input.openAPI(openAPI);
1198+
input.config(codegen);
1199+
1200+
DefaultGenerator generator = new DefaultGenerator();
1201+
codegen.setHateoas(true);
1202+
generator.setGeneratorPropertyDefault(CodegenConstants.MODELS, "true");
1203+
generator.setGeneratorPropertyDefault(CodegenConstants.LEGACY_DISCRIMINATOR_BEHAVIOR, "false");
1204+
1205+
1206+
codegen.setUseOneOfInterfaces(true);
1207+
codegen.setLegacyDiscriminatorBehavior(false);
1208+
codegen.setUseSpringBoot3(true);
1209+
codegen.setModelNameSuffix("DTO");
1210+
1211+
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_TESTS, "false");
1212+
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_DOCS, "false");
1213+
generator.setGeneratorPropertyDefault(CodegenConstants.APIS, "true");
1214+
generator.setGeneratorPropertyDefault(CodegenConstants.SUPPORTING_FILES, "false");
1215+
1216+
generator.opts(input).generate();
1217+
1218+
1219+
assertFileContains(Paths.get(outputPath + "/src/main/java/org/openapitools/model/ChildWithoutMappingADTO.java"), "@JsonTypeName");
1220+
assertFileContains(Paths.get(outputPath + "/src/main/java/org/openapitools/model/ChildWithoutMappingBDTO.java"), "@JsonTypeName");
1221+
}
1222+
11441223
@Test
11451224
public void testTypeMappings() {
11461225
final SpringCodegen codegen = new SpringCodegen();
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
openapi: '3.0.0'
2+
info:
3+
version: '1.0.0'
4+
title: 'FooService'
5+
paths:
6+
/parentWithMapping:
7+
put:
8+
tags:
9+
- pet
10+
summary: put parent
11+
operationId: putParentWithMapping
12+
requestBody:
13+
description: The updated account definition to save.
14+
required: true
15+
content:
16+
application/json:
17+
schema:
18+
$ref: '#/components/schemas/ParentWithMapping'
19+
responses:
20+
'200':
21+
$ref: '#/components/responses/ParentWithMapping'
22+
/parentWithoutMapping:
23+
put:
24+
tags:
25+
- pet
26+
summary: put parent
27+
operationId: putParentWithoutMapping
28+
requestBody:
29+
description: The updated account definition to save.
30+
required: true
31+
content:
32+
application/json:
33+
schema:
34+
$ref: '#/components/schemas/ParentWithoutMapping'
35+
responses:
36+
'200':
37+
$ref: '#/components/responses/ParentWithoutMapping'
38+
components:
39+
schemas:
40+
ParentWithMapping:
41+
type: object
42+
description: Defines an account by name.
43+
properties:
44+
childType:
45+
$ref: '#/components/schemas/ChildType'
46+
required:
47+
- type
48+
discriminator:
49+
propertyName: childType
50+
mapping:
51+
child_a: '#/components/schemas/ChildWithMappingA'
52+
child_b: '#/components/schemas/ChildWithMappingB'
53+
54+
ChildWithMappingA:
55+
allOf:
56+
- $ref: "#/components/schemas/ParentWithMapping"
57+
- type: object
58+
properties:
59+
nameA:
60+
type: string
61+
ChildWithMappingB:
62+
allOf:
63+
- $ref: "#/components/schemas/ParentWithMapping"
64+
- type: object
65+
properties:
66+
nameB:
67+
type: string
68+
ChildType:
69+
type: string
70+
x-extensible-enum:
71+
- child_a
72+
- child_b
73+
ParentWithoutMapping:
74+
type: object
75+
description: Defines an account by name.
76+
properties:
77+
childType:
78+
$ref: '#/components/schemas/ChildType'
79+
required:
80+
- type
81+
discriminator:
82+
propertyName: childType
83+
ChildWithoutMappingA:
84+
allOf:
85+
- $ref: "#/components/schemas/ParentWithoutMapping"
86+
- type: object
87+
properties:
88+
nameA:
89+
type: string
90+
ChildWithoutMappingB:
91+
allOf:
92+
- $ref: "#/components/schemas/ParentWithoutMapping"
93+
- type: object
94+
properties:
95+
nameB:
96+
type: string
97+
responses:
98+
ParentWithMapping:
99+
description: OK
100+
content:
101+
application/json:
102+
schema:
103+
$ref: '#/components/schemas/ParentWithMapping'
104+
ParentWithoutMapping:
105+
description: The saved account definition.
106+
content:
107+
application/json:
108+
schema:
109+
$ref: '#/components/schemas/ParentWithoutMapping'

samples/client/petstore/spring-http-interface/src/main/java/org/openapitools/model/AnimalDto.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
@JsonSubTypes.Type(value = DogDto.class, name = "Dog")
3535
})
3636

37-
@JsonTypeName("Animal")
3837
@Generated(value = "org.openapitools.codegen.languages.SpringCodegen")
3938
public class AnimalDto {
4039

samples/client/petstore/spring-http-interface/src/main/java/org/openapitools/model/CatDto.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
@JsonSubTypes.Type(value = BigCatDto.class, name = "BigCat")
3232
})
3333

34-
@JsonTypeName("Cat")
3534
@Generated(value = "org.openapitools.codegen.languages.SpringCodegen")
3635
public class CatDto extends AnimalDto {
3736

samples/server/petstore/springboot/src/main/java/org/openapitools/model/AnimalDto.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
@JsonSubTypes.Type(value = DogDto.class, name = "Dog")
3838
})
3939

40-
@JsonTypeName("Animal")
4140
@Generated(value = "org.openapitools.codegen.languages.SpringCodegen")
4241
public class AnimalDto {
4342

samples/server/petstore/springboot/src/main/java/org/openapitools/model/CatDto.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
@JsonSubTypes.Type(value = BigCatDto.class, name = "BigCat")
3535
})
3636

37-
@JsonTypeName("Cat")
3837
@Generated(value = "org.openapitools.codegen.languages.SpringCodegen")
3938
public class CatDto extends AnimalDto {
4039

0 commit comments

Comments
 (0)