Skip to content

Commit 8fc8093

Browse files
committed
Fix #1022 - Discriminator should only add Jackson JsonSubTypes when there's a parent class
Signed-off-by: Ricardo Zanini <[email protected]>
1 parent bb43278 commit 8fc8093

File tree

4 files changed

+162
-2
lines changed

4 files changed

+162
-2
lines changed

client/deployment/src/main/resources/templates/libraries/microprofile/pojo.qute

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
77
**/
88
{/if}
99
{#include additionalModelTypeAnnotations.qute m=m/}
10-
{#if m.discriminator && m.discriminator.mappedModels && !m.discriminator.mappedModels.empty}
10+
{#if m.discriminator && m.discriminator.mappedModels && !m.discriminator.mappedModels.empty && m.children}
1111
@com.fasterxml.jackson.annotation.JsonIgnoreProperties(
1212
value = "{m.discriminator.propertyBaseName}", // ignore manually set {m.discriminator.propertyBaseName}, it will be automatically generated by Jackson during serialization
1313
allowSetters = true // allows the {m.discriminator.propertyBaseName} to be set during deserialization

client/deployment/src/test/java/io/quarkiverse/openapi/generator/deployment/wrapper/OpenApiClientGeneratorWrapperTest.java

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,13 @@ void verifyOAuthDuplicateAnnotationOnCompositeAuthProvider() throws URISyntaxExc
8484
assertThat(oauthAnnotationsCount).isEqualTo(1);
8585
}
8686

87+
/**
88+
* If the specification component has `oneOf` specified instead of `allOf`, the inner generator won't create a hierarchy of
89+
* classes.
90+
* In this situation, we can't generate the `JsonSubTypes` annotations.
91+
*/
8792
@Test
88-
void verifyDiscriminatorGeneration() throws java.net.URISyntaxException, FileNotFoundException {
93+
void verifyOneOfDiscriminatorGeneration() throws java.net.URISyntaxException, FileNotFoundException {
8994
OpenApiClientGeneratorWrapper generatorWrapper = createGeneratorWrapper("issue-852.json");
9095
final List<File> generatedFiles = generatorWrapper.generate("org.issue852");
9196

@@ -96,6 +101,30 @@ void verifyDiscriminatorGeneration() throws java.net.URISyntaxException, FileNot
96101
.filter(f -> f.getName().endsWith("PostRevisionForDocumentRequest.java")).findFirst();
97102
assertThat(classWithDiscriminator).isPresent();
98103

104+
final CompilationUnit compilationUnit = StaticJavaParser.parse(classWithDiscriminator.orElseThrow());
105+
assertThat(compilationUnit.findFirst(ClassOrInterfaceDeclaration.class)
106+
.flatMap(first -> first.getAnnotationByClass(com.fasterxml.jackson.annotation.JsonSubTypes.class)))
107+
.isNotPresent();
108+
}
109+
110+
/**
111+
* Only generates `JsonSubTypes` annotations in case the class has children, otherwise skip since Jackson will complain in
112+
* runtime.
113+
* The file issue-1022.json is a classic example of a spec with allOf to denote how the Java POJO should be and how Jackson
114+
* would serialize.
115+
*/
116+
@Test
117+
void verifyAllOfDiscriminatorGeneration() throws java.net.URISyntaxException, FileNotFoundException {
118+
OpenApiClientGeneratorWrapper generatorWrapper = createGeneratorWrapper("issue-1022.json");
119+
final List<File> generatedFiles = generatorWrapper.generate("org.issue1022");
120+
121+
assertNotNull(generatedFiles);
122+
assertFalse(generatedFiles.isEmpty());
123+
124+
final Optional<File> classWithDiscriminator = generatedFiles.stream()
125+
.filter(f -> f.getName().startsWith("Thing.java")).findFirst();
126+
assertThat(classWithDiscriminator).isPresent();
127+
99128
final CompilationUnit compilationUnit = StaticJavaParser.parse(classWithDiscriminator.orElseThrow());
100129
assertThat(compilationUnit.findFirst(ClassOrInterfaceDeclaration.class)
101130
.flatMap(first -> first.getAnnotationByClass(com.fasterxml.jackson.annotation.JsonSubTypes.class)))
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
{
2+
"openapi": "3.0.3",
3+
"info": {
4+
"title": "tuto API",
5+
"version": "1.0.0-SNAPSHOT"
6+
},
7+
"servers": [
8+
{
9+
"url": "http://localhost:8080",
10+
"description": "Auto generated value"
11+
},
12+
{
13+
"url": "http://0.0.0.0:8080",
14+
"description": "Auto generated value"
15+
}
16+
],
17+
"paths": {
18+
"/": {
19+
"get": {
20+
"tags": [
21+
"Default"
22+
],
23+
"operationId": "get",
24+
"responses": {
25+
"200": {
26+
"description": "OK",
27+
"content": {
28+
"application/json": {
29+
"schema": {
30+
"$ref": "#/components/schemas/Data"
31+
}
32+
}
33+
}
34+
}
35+
}
36+
}
37+
}
38+
},
39+
"components": {
40+
"schemas": {
41+
"Data": {
42+
"required": [
43+
"things"
44+
],
45+
"type": "object",
46+
"properties": {
47+
"things": {
48+
"type": "array",
49+
"items": {
50+
"$ref": "#/components/schemas/Thing"
51+
},
52+
"anyOf": [
53+
{
54+
"$ref": "#/components/schemas/SomeThing"
55+
},
56+
{
57+
"$ref": "#/components/schemas/OtherThing"
58+
}
59+
]
60+
}
61+
}
62+
},
63+
"OtherThing": {
64+
"description": "Other thing",
65+
"required": [
66+
"other"
67+
],
68+
"type": "object",
69+
"allOf": [
70+
{
71+
"$ref": "#/components/schemas/Thing"
72+
}
73+
],
74+
"properties": {
75+
"other": {
76+
"type": "string"
77+
}
78+
}
79+
},
80+
"SomeThing": {
81+
"description": "Some thing",
82+
"required": [
83+
"some"
84+
],
85+
"type": "object",
86+
"allOf": [
87+
{
88+
"$ref": "#/components/schemas/Thing"
89+
}
90+
],
91+
"properties": {
92+
"some": {
93+
"type": "string"
94+
}
95+
}
96+
},
97+
"Thing": {
98+
"description": "Thing",
99+
"required": [
100+
"thing"
101+
],
102+
"type": "object",
103+
"properties": {
104+
"thing": {
105+
"type": "string"
106+
}
107+
},
108+
"discriminator": {
109+
"propertyName": "@type",
110+
"mapping": {
111+
"SomeThing": "#/components/schemas/SomeThing",
112+
"OtherThing": "#/components/schemas/OtherThing"
113+
}
114+
}
115+
}
116+
}
117+
}
118+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[.configuration-legend]
2+
icon:lock[title=Fixed at build time] Configuration property fixed at build time - All other configuration properties are overridable at runtime
3+
[.configuration-reference.searchable, cols="80,.^10,.^10"]
4+
|===
5+
6+
h|[.header-title]##Configuration property##
7+
h|Type
8+
h|Default
9+
10+
3+|No configuration properties found.
11+
12+
|===
13+

0 commit comments

Comments
 (0)