Skip to content

Commit f77d733

Browse files
committed
fix jsonmapping
1 parent 1b4b790 commit f77d733

3 files changed

Lines changed: 84 additions & 57 deletions

File tree

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
import java.util.stream.Stream;
7272
import java.util.stream.StreamSupport;
7373

74+
import static org.openapitools.codegen.CodegenConstants.X_DISCRIMINATOR_VALUE;
7475
import static org.openapitools.codegen.CodegenConstants.X_IMPLEMENTS;
7576
import static org.openapitools.codegen.utils.CamelizeOption.*;
7677
import static org.openapitools.codegen.utils.ModelUtils.getSchemaItems;
@@ -802,6 +803,23 @@ public Map<String, ModelsMap> postProcessAllModels(Map<String, ModelsMap> objs)
802803
}
803804
}
804805

806+
// Propagate the parent's discriminator mapping key to each child model's vendorExtensions
807+
// as x-discriminator-value, so that @JsonTypeName on the child matches the parent's
808+
// @JsonSubTypes name when an explicit discriminator mapping renames the key
809+
// (e.g. "child_a" instead of the schema name "ChildWithMappingA").
810+
// putIfAbsent preserves any value the user has already set explicitly in the spec.
811+
for (CodegenModel cm : allModels.values()) {
812+
if (cm.getParentModel() == null || cm.getParentModel().getDiscriminator() == null) {
813+
continue;
814+
}
815+
for (CodegenDiscriminator.MappedModel mm : cm.getParentModel().getDiscriminator().getMappedModels()) {
816+
if (mm.getModelName().equals(cm.classname)) {
817+
cm.vendorExtensions.putIfAbsent(X_DISCRIMINATOR_VALUE, mm.getMappingName());
818+
break;
819+
}
820+
}
821+
}
822+
805823
return objs;
806824
}
807825

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
{{#jackson}}
2323
{{#isClassnameSanitized}}
2424
{{#parent}}
25-
@JsonTypeName("{{name}}")
25+
@JsonTypeName("{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}{{^vendorExtensions.x-discriminator-value}}{{name}}{{/vendorExtensions.x-discriminator-value}}")
2626
{{/parent}}
2727
{{^parent}}
2828
{{^hasDiscriminatorWithNonEmptyMapping}}

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

Lines changed: 65 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,7 @@
6565
import static org.openapitools.codegen.languages.SpringCodegen.*;
6666
import static org.openapitools.codegen.languages.features.DocumentationProviderFeatures.ANNOTATION_LIBRARY;
6767
import static org.openapitools.codegen.languages.features.DocumentationProviderFeatures.DOCUMENTATION_PROVIDER;
68-
import static org.testng.Assert.assertEquals;
69-
import static org.testng.Assert.assertNotNull;
70-
import static org.testng.Assert.fail;
68+
import static org.testng.Assert.*;
7169

7270
public class SpringCodegenTest {
7371

@@ -898,16 +896,16 @@ public void testReactiveMultipartBoot() throws IOException {
898896

899897
// Check that the delegate handles the array
900898
JavaFileAssert.assertThat(files.get("MultipartArrayApiDelegate.java"))
901-
.assertMethod("multipartArray", "Flux<Part>", "ServerWebExchange")
902-
.assertParameter("files").hasType("Flux<Part>");
899+
.assertMethod("multipartArray", "Flux<Part>", "ServerWebExchange")
900+
.assertParameter("files").hasType("Flux<Part>");
903901

904902
// Check that the api handles the array
905903
JavaFileAssert.assertThat(files.get("MultipartArrayApi.java"))
906-
.assertMethod("multipartArray", "Flux<Part>", "ServerWebExchange")
907-
.assertParameter("files").hasType("Flux<Part>")
908-
.assertParameterAnnotations()
909-
.containsWithNameAndAttributes("ApiParam", ImmutableMap.of("value", "\"Many files\""))
910-
.containsWithNameAndAttributes("RequestPart", ImmutableMap.of("value", "\"files\"", "required", "false"));
904+
.assertMethod("multipartArray", "Flux<Part>", "ServerWebExchange")
905+
.assertParameter("files").hasType("Flux<Part>")
906+
.assertParameterAnnotations()
907+
.containsWithNameAndAttributes("ApiParam", ImmutableMap.of("value", "\"Many files\""))
908+
.containsWithNameAndAttributes("RequestPart", ImmutableMap.of("value", "\"files\"", "required", "false"));
911909

912910
// UPDATE: the following test has been ignored due to https://github.com/OpenAPITools/openapi-generator/pull/11081/
913911
// We will contact the contributor of the following test to see if the fix will break their use cases and
@@ -918,32 +916,32 @@ public void testReactiveMultipartBoot() throws IOException {
918916

919917
// Check that the api handles the single file
920918
JavaFileAssert.assertThat(files.get("MultipartSingleApi.java"))
921-
.assertMethod("multipartSingle", "Part", "ServerWebExchange")
922-
.assertParameter("file").hasType("Part")
923-
.assertParameterAnnotations()
924-
.containsWithNameAndAttributes("ApiParam", ImmutableMap.of("value", "\"One file\""))
925-
.containsWithNameAndAttributes("RequestPart", ImmutableMap.of("value", "\"file\"", "required", "false"));
919+
.assertMethod("multipartSingle", "Part", "ServerWebExchange")
920+
.assertParameter("file").hasType("Part")
921+
.assertParameterAnnotations()
922+
.containsWithNameAndAttributes("ApiParam", ImmutableMap.of("value", "\"One file\""))
923+
.containsWithNameAndAttributes("RequestPart", ImmutableMap.of("value", "\"file\"", "required", "false"));
926924

927925
// Check that api validates mixed multipart request
928926
JavaFileAssert.assertThat(files.get("MultipartMixedApi.java"))
929-
.assertMethod("multipartMixed", "MultipartMixedStatus", "Part", "MultipartMixedRequestMarker", "List<MultipartMixedStatus>", "ServerWebExchange")
930-
.assertParameter("status").hasType("MultipartMixedStatus")
931-
.assertParameterAnnotations()
932-
.containsWithName("Valid")
933-
.containsWithNameAndAttributes("ApiParam", ImmutableMap.of("value", "\"\""))
934-
.containsWithNameAndAttributes("RequestPart", ImmutableMap.of("value", "\"status\"", "required", "true"))
935-
.toParameter().toMethod()
936-
.assertParameter("file").hasType("Part")
937-
.assertParameterAnnotations()
938-
.containsWithNameAndAttributes("RequestPart", ImmutableMap.of("value", "\"file\"", "required", "true"))
939-
.toParameter().toMethod()
940-
.assertParameter("marker").hasType("MultipartMixedRequestMarker")
941-
.assertParameterAnnotations()
942-
.containsWithNameAndAttributes("RequestPart", ImmutableMap.of("value", "\"marker\"", "required", "false"))
943-
.toParameter().toMethod()
944-
.assertParameter("statusArray").hasType("List<MultipartMixedStatus>")
945-
.assertParameterAnnotations()
946-
.containsWithNameAndAttributes("RequestPart", ImmutableMap.of("value", "\"statusArray\"", "required", "false"));
927+
.assertMethod("multipartMixed", "MultipartMixedStatus", "Part", "MultipartMixedRequestMarker", "List<MultipartMixedStatus>", "ServerWebExchange")
928+
.assertParameter("status").hasType("MultipartMixedStatus")
929+
.assertParameterAnnotations()
930+
.containsWithName("Valid")
931+
.containsWithNameAndAttributes("ApiParam", ImmutableMap.of("value", "\"\""))
932+
.containsWithNameAndAttributes("RequestPart", ImmutableMap.of("value", "\"status\"", "required", "true"))
933+
.toParameter().toMethod()
934+
.assertParameter("file").hasType("Part")
935+
.assertParameterAnnotations()
936+
.containsWithNameAndAttributes("RequestPart", ImmutableMap.of("value", "\"file\"", "required", "true"))
937+
.toParameter().toMethod()
938+
.assertParameter("marker").hasType("MultipartMixedRequestMarker")
939+
.assertParameterAnnotations()
940+
.containsWithNameAndAttributes("RequestPart", ImmutableMap.of("value", "\"marker\"", "required", "false"))
941+
.toParameter().toMethod()
942+
.assertParameter("statusArray").hasType("List<MultipartMixedStatus>")
943+
.assertParameterAnnotations()
944+
.containsWithNameAndAttributes("RequestPart", ImmutableMap.of("value", "\"statusArray\"", "required", "false"));
947945
}
948946

949947
@Test
@@ -2063,8 +2061,14 @@ public void testDiscriminatorWithMappingIssue14731() throws IOException {
20632061

20642062
generator.opts(input).generate();
20652063

2066-
assertFileNotContains(Paths.get(outputPath + "/src/main/java/org/openapitools/model/ChildWithMappingADTO.java"), "@JsonTypeName");
2067-
assertFileNotContains(Paths.get(outputPath + "/src/main/java/org/openapitools/model/ChildWithMappingBDTO.java"), "@JsonTypeName");
2064+
assertFileContains(Paths.get(outputPath + "/src/main/java/org/openapitools/model/ParentWithMappingDTO.java"),
2065+
"@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = \"childType\", visible = true)\n"
2066+
+ "@JsonSubTypes({\n"
2067+
+ " @JsonSubTypes.Type(value = ChildWithMappingADTO.class, name = \"child_a\"),\n"
2068+
+ " @JsonSubTypes.Type(value = ChildWithMappingBDTO.class, name = \"child_b\")\n"
2069+
+ "})");
2070+
assertFileContains(Paths.get(outputPath + "/src/main/java/org/openapitools/model/ChildWithMappingADTO.java"), "@JsonTypeName(\"child_a\")");
2071+
assertFileContains(Paths.get(outputPath + "/src/main/java/org/openapitools/model/ChildWithMappingBDTO.java"), "@JsonTypeName(\"child_b\")");
20682072
}
20692073

20702074
@Test
@@ -2100,9 +2104,14 @@ public void testDiscriminatorWithoutMappingIssue14731() throws IOException {
21002104

21012105
generator.opts(input).generate();
21022106

2103-
2104-
assertFileContains(Paths.get(outputPath + "/src/main/java/org/openapitools/model/ChildWithoutMappingADTO.java"), "@JsonTypeName");
2105-
assertFileContains(Paths.get(outputPath + "/src/main/java/org/openapitools/model/ChildWithoutMappingBDTO.java"), "@JsonTypeName");
2107+
assertFileContains(Paths.get(outputPath + "/src/main/java/org/openapitools/model/ParentWithoutMappingDTO.java"),
2108+
"@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = \"childType\", visible = true)\n"
2109+
+ "@JsonSubTypes({\n"
2110+
+ " @JsonSubTypes.Type(value = ChildWithoutMappingADTO.class, name = \"ChildWithoutMappingA\"),\n"
2111+
+ " @JsonSubTypes.Type(value = ChildWithoutMappingBDTO.class, name = \"ChildWithoutMappingB\")\n"
2112+
+ "})");
2113+
assertFileContains(Paths.get(outputPath + "/src/main/java/org/openapitools/model/ChildWithoutMappingADTO.java"), "@JsonTypeName(\"ChildWithoutMappingA\")");
2114+
assertFileContains(Paths.get(outputPath + "/src/main/java/org/openapitools/model/ChildWithoutMappingBDTO.java"), "@JsonTypeName(\"ChildWithoutMappingB\")");
21062115
}
21072116

21082117
@Test
@@ -6306,46 +6315,46 @@ public void testXMinimumMessageAndXMaximumMessage_long() throws IOException {
63066315
.assertParameter("number")
63076316
.assertParameterAnnotations()
63086317
.containsWithNameAndAttributes("Min", ImmutableMap.of(
6309-
"value", "1L",
6318+
"value", "1L",
63106319
"message", "\"Must be positive\""
63116320
))
63126321
.containsWithNameAndAttributes("Max", ImmutableMap.of(
6313-
"value", "99L",
6322+
"value", "99L",
63146323
"message", "\"Must be less than 100\""
63156324
))
63166325
.toParameter()
63176326
.toMethod()
63186327
.assertParameter("token")
63196328
.assertParameterAnnotations()
63206329
.containsWithNameAndAttributes("Min", ImmutableMap.of(
6321-
"value", "1L",
6330+
"value", "1L",
63226331
"message", "\"Must be positive\""
63236332
))
63246333
.containsWithNameAndAttributes("Max", ImmutableMap.of(
6325-
"value", "99L",
6334+
"value", "99L",
63266335
"message", "\"Must be less than 100\""
63276336
))
63286337
.toParameter()
63296338
.toMethod()
63306339
.assertParameter("clientNumber")
63316340
.assertParameterAnnotations()
63326341
.containsWithNameAndAttributes("Min", ImmutableMap.of(
6333-
"value", "1L",
6342+
"value", "1L",
63346343
"message", "\"Must be positive\""
63356344
))
63366345
.containsWithNameAndAttributes("Max", ImmutableMap.of(
6337-
"value", "99L",
6346+
"value", "99L",
63386347
"message", "\"Must be less than 100\""
63396348
));
63406349
JavaFileAssert.assertThat(files.get("LongTest.java"))
63416350
.assertMethod("getField1")
63426351
.assertMethodAnnotations()
63436352
.containsWithNameAndAttributes("Min", ImmutableMap.of(
6344-
"value", "1L",
6353+
"value", "1L",
63456354
"message", "\"Must be positive\""
63466355
))
63476356
.containsWithNameAndAttributes("Max", ImmutableMap.of(
6348-
"value", "99L",
6357+
"value", "99L",
63496358
"message", "\"Must be less than 100\""
63506359
))
63516360
.toMethod()
@@ -6374,19 +6383,19 @@ public void annotationLibraryDoesNotCauseImportConflictsInSpring() throws IOExce
63746383
codegen.additionalProperties().putAll(properties);
63756384

63766385
ClientOptInput input = new ClientOptInput()
6377-
.openAPI(openAPI)
6378-
.config(codegen);
6386+
.openAPI(openAPI)
6387+
.config(codegen);
63796388

63806389
DefaultGenerator generator = new DefaultGenerator();
63816390

63826391
Map<String, File> files = generator.opts(input).generate().stream()
6383-
.collect(Collectors.toMap(File::getName, Function.identity()));
6392+
.collect(Collectors.toMap(File::getName, Function.identity()));
63846393

63856394
File apiFile = files.get("Schema.java");
63866395
assertNotNull(apiFile);
63876396

63886397
JavaFileAssert.assertThat(apiFile).fileDoesNotContain(
6389-
"import io.swagger.v3.oas.annotations.media.Schema;"
6398+
"import io.swagger.v3.oas.annotations.media.Schema;"
63906399
);
63916400
}
63926401

@@ -6408,19 +6417,19 @@ public void annotationLibraryDoesNotCauseImportConflictsInSpringWithAnnotationLi
64086417
codegen.additionalProperties().putAll(properties);
64096418

64106419
ClientOptInput input = new ClientOptInput()
6411-
.openAPI(openAPI)
6412-
.config(codegen);
6420+
.openAPI(openAPI)
6421+
.config(codegen);
64136422

64146423
DefaultGenerator generator = new DefaultGenerator();
64156424

64166425
Map<String, File> files = generator.opts(input).generate().stream()
6417-
.collect(Collectors.toMap(File::getName, Function.identity()));
6426+
.collect(Collectors.toMap(File::getName, Function.identity()));
64186427

64196428
File apiFile = files.get("Schema.java");
64206429
assertNotNull(apiFile);
64216430

64226431
JavaFileAssert.assertThat(apiFile).fileContains(
6423-
"import io.swagger.v3.oas.annotations.media.Schema;"
6432+
"import io.swagger.v3.oas.annotations.media.Schema;"
64246433
);
64256434
}
64266435

@@ -6460,15 +6469,15 @@ public void testExtensionsOnSchema_issue9183() throws IOException {
64606469
.containsWithNameAndAttributes("Pattern", ImmutableMap.of(
64616470
"regexp", "\"[a-zA-Z]\"",
64626471
"message", "\"Only letters\""
6463-
))
6472+
))
64646473
.toParameter()
64656474
.toMethod()
64666475
.assertParameter("token")
64676476
.assertParameterAnnotations()
64686477
.containsWithNameAndAttributes("Pattern", ImmutableMap.of(
64696478
"regexp", "\"[0-9a-fA-F]\"",
64706479
"message", "\"Only numbers and letters a-f\""
6471-
));
6480+
));
64726481
}
64736482

64746483
@Test

0 commit comments

Comments
 (0)