Skip to content

Commit 73b38dd

Browse files
konopskiwing328
authored andcommitted
#3904 Inheritance support java client retrofit gson (#4729)
* merge with master * remove zoo specific artifact names * fix duplicate doublequote * #3904 add samples for retrofit2 * #3904 clean json field retrieval * #3904 allow non-abstract parent class
1 parent 1dc3fb4 commit 73b38dd

File tree

12 files changed

+157
-2
lines changed

12 files changed

+157
-2
lines changed

modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultGenerator.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,7 @@ public List<File> generate() {
708708
return files;
709709
}
710710

711+
711712
private File processTemplateToFile(Map<String, Object> templateData, String templateName, String outputFilename) throws IOException {
712713
String adjustedOutputFilename = outputFilename.replaceAll("//", "/").replace('/', File.separatorChar);
713714
if (ignoreProcessor.allowsFile(new File(adjustedOutputFilename))) {

modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaClientCodegen.java

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.swagger.codegen.languages;
22

3+
import com.google.common.collect.LinkedListMultimap;
34
import io.swagger.codegen.*;
45
import io.swagger.codegen.languages.features.BeanValidationFeatures;
56
import io.swagger.codegen.languages.features.GzipFeatures;
@@ -432,6 +433,24 @@ public void postProcessModelProperty(CodegenModel model, CodegenProperty propert
432433
}
433434

434435
@SuppressWarnings("unchecked")
436+
@Override
437+
public Map<String, Object> postProcessAllModels(Map<String, Object> objs) {
438+
Map<String, Object> allProcessedModels = super.postProcessAllModels(objs);
439+
if(!additionalProperties.containsKey("gsonFactoryMethod")) {
440+
List<Object> allModels = new ArrayList<Object>();
441+
for (String name: allProcessedModels.keySet()) {
442+
Map<String, Object> models = (Map<String, Object>)allProcessedModels.get(name);
443+
try {
444+
allModels.add(((List<Object>) models.get("models")).get(0));
445+
} catch (Exception e){
446+
e.printStackTrace();
447+
}
448+
}
449+
additionalProperties.put("parent", modelInheritanceSupportInGson(allModels));
450+
}
451+
return allProcessedModels;
452+
}
453+
435454
@Override
436455
public Map<String, Object> postProcessModelsEnum(Map<String, Object> objs) {
437456
objs = super.postProcessModelsEnum(objs);
@@ -454,6 +473,34 @@ public Map<String, Object> postProcessModelsEnum(Map<String, Object> objs) {
454473
return objs;
455474
}
456475

476+
private List<Map<String, Object>> modelInheritanceSupportInGson(List<?> allModels) {
477+
LinkedListMultimap<CodegenModel, CodegenModel> byParent = LinkedListMultimap.create();
478+
for (Object m : allModels) {
479+
Map entry = (Map) m;
480+
CodegenModel parent = ((CodegenModel)entry.get("model")).parentModel;
481+
if(null!= parent) {
482+
byParent.put(parent, ((CodegenModel)entry.get("model")));
483+
}
484+
}
485+
List<Map<String, Object>> parentsList = new ArrayList<>();
486+
for (CodegenModel parentModel : byParent.keySet()) {
487+
List<Map<String, Object>> childrenList = new ArrayList<>();
488+
Map<String, Object> parent = new HashMap<>();
489+
parent.put("classname", parentModel.classname);
490+
List<CodegenModel> childrenModels = byParent.get(parentModel);
491+
for (CodegenModel model : childrenModels) {
492+
Map<String, Object> child = new HashMap<>();
493+
child.put("name", model.name);
494+
child.put("classname", model.classname);
495+
childrenList.add(child);
496+
}
497+
parent.put("children", childrenList);
498+
parent.put("discriminator", parentModel.discriminator);
499+
parentsList.add(parent);
500+
}
501+
return parentsList;
502+
}
503+
457504
public void setUseRxJava(boolean useRxJava) {
458505
this.useRxJava = useRxJava;
459506
doNotUseRx = false;

modules/swagger-codegen/src/main/resources/Java/libraries/retrofit2/ApiClient.mustache

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package {{invokerPackage}};
22

33
import com.google.gson.Gson;
44
import com.google.gson.JsonParseException;
5+
import com.google.gson.JsonElement;
56
import okhttp3.Interceptor;
67
import okhttp3.OkHttpClient;
78
import okhttp3.RequestBody;
@@ -39,6 +40,7 @@ import java.time.format.DateTimeFormatter;
3940
{{/java8}}
4041
import java.util.LinkedHashMap;
4142
import java.util.Map;
43+
import java.util.HashMap;
4244

4345
public class ApiClient {
4446

modules/swagger-codegen/src/main/resources/Java/libraries/retrofit2/JSON.mustache

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ import com.google.gson.TypeAdapter;
99
import com.google.gson.internal.bind.util.ISO8601Utils;
1010
import com.google.gson.stream.JsonReader;
1111
import com.google.gson.stream.JsonWriter;
12+
import com.google.gson.JsonElement;
13+
import io.gsonfire.GsonFireBuilder;
14+
import io.gsonfire.TypeSelector;
1215
{{#joda}}
1316
import org.joda.time.DateTime;
1417
import org.joda.time.LocalDate;
@@ -22,6 +25,8 @@ import org.threeten.bp.OffsetDateTime;
2225
import org.threeten.bp.format.DateTimeFormatter;
2326
{{/threetenbp}}
2427

28+
import {{modelPackage}}.*;
29+
2530
import java.io.IOException;
2631
import java.io.StringReader;
2732
import java.lang.reflect.Type;
@@ -34,6 +39,8 @@ import java.time.OffsetDateTime;
3439
import java.time.format.DateTimeFormatter;
3540
{{/java8}}
3641
import java.util.Date;
42+
import java.util.Map;
43+
import java.util.HashMap;
3744

3845
public class JSON {
3946
private Gson gson;
@@ -48,8 +55,45 @@ public class JSON {
4855
private LocalDateTypeAdapter localDateTypeAdapter = new LocalDateTypeAdapter();
4956
{{/jsr310}}
5057

58+
public static GsonBuilder createGson() {
59+
GsonFireBuilder fireBuilder = new GsonFireBuilder()
60+
{{#parent}}
61+
.registerTypeSelector({{classname}}.class, new TypeSelector() {
62+
@Override
63+
public Class getClassForElement(JsonElement readElement) {
64+
Map classByDiscriminatorValue = new HashMap();
65+
{{#children}}
66+
classByDiscriminatorValue.put("{{name}}".toUpperCase(), {{classname}}.class);
67+
{{/children}}
68+
classByDiscriminatorValue.put("{{classname}}".toUpperCase(), {{classname}}.class);
69+
return getClassByDiscriminator(
70+
classByDiscriminatorValue,
71+
getDiscriminatorValue(readElement, "{{discriminator}}"));
72+
}
73+
})
74+
{{/parent}}
75+
;
76+
return fireBuilder.createGsonBuilder();
77+
}
78+
79+
private static String getDiscriminatorValue(JsonElement readElement, String discriminatorField) {
80+
JsonElement element = readElement.getAsJsonObject().get(discriminatorField);
81+
if(null == element) {
82+
throw new IllegalArgumentException("missing discriminator field: <" + discriminatorField + ">");
83+
}
84+
return element.getAsString();
85+
}
86+
87+
private static Class getClassByDiscriminator(Map classByDiscriminatorValue, String discriminatorValue) {
88+
Class clazz = (Class) classByDiscriminatorValue.get(discriminatorValue.toUpperCase());
89+
if(null == clazz) {
90+
throw new IllegalArgumentException("cannot determine model class of name: <" + discriminatorValue + ">");
91+
}
92+
return clazz;
93+
}
94+
5195
public JSON() {
52-
gson = new GsonBuilder()
96+
gson = createGson()
5397
.registerTypeAdapter(Date.class, dateTypeAdapter)
5498
.registerTypeAdapter(java.sql.Date.class, sqlDateTypeAdapter)
5599
{{#joda}}

modules/swagger-codegen/src/main/resources/Java/libraries/retrofit2/build.gradle.mustache

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ ext {
126126
{{#threetenbp}}
127127
threetenbp_version = "1.3.5"
128128
{{/threetenbp}}
129+
json_fire_version = "1.8.0"
129130
}
130131

131132
dependencies {
@@ -142,6 +143,7 @@ dependencies {
142143
{{/useRxJava2}}
143144
compile "io.swagger:swagger-annotations:$swagger_annotations_version"
144145
compile "org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:$oltu_version"
146+
compile "io.gsonfire:gson-fire:$json_fire_version"
145147
{{#joda}}
146148
compile "joda-time:joda-time:$jodatime_version"
147149
{{/joda}}

modules/swagger-codegen/src/main/resources/Java/libraries/retrofit2/build.sbt.mustache

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ lazy val root = (project in file(".")).
4545
{{#threetenbp}}
4646
"org.threeten" % "threetenbp" % "1.3.5" % "compile",
4747
{{/threetenbp}}
48+
"io.gsonfire" % "gson-fire" % "1.8.0" % "compile",
4849
"junit" % "junit" % "4.12" % "test",
4950
"com.novocode" % "junit-interface" % "0.11" % "test"
5051
)

modules/swagger-codegen/src/main/resources/Java/libraries/retrofit2/pom.mustache

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,11 @@
194194
<artifactId>org.apache.oltu.oauth2.client</artifactId>
195195
<version>${oltu-version}</version>
196196
</dependency>
197+
<dependency>
198+
<groupId>io.gsonfire</groupId>
199+
<artifactId>gson-fire</artifactId>
200+
<version>${gson-fire-version}</version>
201+
</dependency>
197202
{{#joda}}
198203
<dependency>
199204
<groupId>joda-time</groupId>
@@ -300,6 +305,7 @@
300305
<java.version>{{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}}</java.version>
301306
<maven.compiler.source>${java.version}</maven.compiler.source>
302307
<maven.compiler.target>${java.version}</maven.compiler.target>
308+
<gson-fire-version>1.8.0</gson-fire-version>
303309
<swagger-core-version>1.5.15</swagger-core-version>
304310
{{#usePlayWS}}
305311
{{#play24}}

samples/client/petstore/java/retrofit2/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ ext {
9999
swagger_annotations_version = "1.5.15"
100100
junit_version = "4.12"
101101
threetenbp_version = "1.3.5"
102+
json_fire_version = "1.8.0"
102103
}
103104

104105
dependencies {
@@ -107,6 +108,7 @@ dependencies {
107108
compile "com.squareup.retrofit2:converter-gson:$retrofit_version"
108109
compile "io.swagger:swagger-annotations:$swagger_annotations_version"
109110
compile "org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:$oltu_version"
111+
compile "io.gsonfire:gson-fire:$json_fire_version"
110112
compile "org.threeten:threetenbp:$threetenbp_version"
111113

112114
testCompile "junit:junit:$junit_version"

samples/client/petstore/java/retrofit2/build.sbt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ lazy val root = (project in file(".")).
1515
"io.swagger" % "swagger-annotations" % "1.5.15" % "compile",
1616
"org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1" % "compile",
1717
"org.threeten" % "threetenbp" % "1.3.5" % "compile",
18+
"io.gsonfire" % "gson-fire" % "1.8.0" % "compile",
1819
"junit" % "junit" % "4.12" % "test",
1920
"com.novocode" % "junit-interface" % "0.11" % "test"
2021
)

samples/client/petstore/java/retrofit2/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,11 @@
194194
<artifactId>org.apache.oltu.oauth2.client</artifactId>
195195
<version>${oltu-version}</version>
196196
</dependency>
197+
<dependency>
198+
<groupId>io.gsonfire</groupId>
199+
<artifactId>gson-fire</artifactId>
200+
<version>${gson-fire-version}</version>
201+
</dependency>
197202
<dependency>
198203
<groupId>org.threeten</groupId>
199204
<artifactId>threetenbp</artifactId>
@@ -215,6 +220,7 @@
215220
<java.version>1.7</java.version>
216221
<maven.compiler.source>${java.version}</maven.compiler.source>
217222
<maven.compiler.target>${java.version}</maven.compiler.target>
223+
<gson-fire-version>1.8.0</gson-fire-version>
218224
<swagger-core-version>1.5.15</swagger-core-version>
219225
<retrofit-version>2.3.0</retrofit-version>
220226
<threetenbp-version>1.3.5</threetenbp-version>

samples/client/petstore/java/retrofit2/src/main/java/io/swagger/client/ApiClient.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.google.gson.Gson;
44
import com.google.gson.JsonParseException;
5+
import com.google.gson.JsonElement;
56
import okhttp3.Interceptor;
67
import okhttp3.OkHttpClient;
78
import okhttp3.RequestBody;
@@ -25,6 +26,7 @@
2526
import java.text.DateFormat;
2627
import java.util.LinkedHashMap;
2728
import java.util.Map;
29+
import java.util.HashMap;
2830

2931
public class ApiClient {
3032

samples/client/petstore/java/retrofit2/src/main/java/io/swagger/client/JSON.java

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,24 @@
2020
import com.google.gson.internal.bind.util.ISO8601Utils;
2121
import com.google.gson.stream.JsonReader;
2222
import com.google.gson.stream.JsonWriter;
23+
import com.google.gson.JsonElement;
24+
import io.gsonfire.GsonFireBuilder;
25+
import io.gsonfire.TypeSelector;
2326
import org.threeten.bp.LocalDate;
2427
import org.threeten.bp.OffsetDateTime;
2528
import org.threeten.bp.format.DateTimeFormatter;
2629

30+
import io.swagger.client.model.*;
31+
2732
import java.io.IOException;
2833
import java.io.StringReader;
2934
import java.lang.reflect.Type;
3035
import java.text.DateFormat;
3136
import java.text.ParseException;
3237
import java.text.ParsePosition;
3338
import java.util.Date;
39+
import java.util.Map;
40+
import java.util.HashMap;
3441

3542
public class JSON {
3643
private Gson gson;
@@ -39,8 +46,42 @@ public class JSON {
3946
private OffsetDateTimeTypeAdapter offsetDateTimeTypeAdapter = new OffsetDateTimeTypeAdapter();
4047
private LocalDateTypeAdapter localDateTypeAdapter = new LocalDateTypeAdapter();
4148

49+
public static GsonBuilder createGson() {
50+
GsonFireBuilder fireBuilder = new GsonFireBuilder()
51+
.registerTypeSelector(Animal.class, new TypeSelector() {
52+
@Override
53+
public Class getClassForElement(JsonElement readElement) {
54+
Map classByDiscriminatorValue = new HashMap();
55+
classByDiscriminatorValue.put("Cat".toUpperCase(), Cat.class);
56+
classByDiscriminatorValue.put("Dog".toUpperCase(), Dog.class);
57+
classByDiscriminatorValue.put("Animal".toUpperCase(), Animal.class);
58+
return getClassByDiscriminator(
59+
classByDiscriminatorValue,
60+
getDiscriminatorValue(readElement, "className"));
61+
}
62+
})
63+
;
64+
return fireBuilder.createGsonBuilder();
65+
}
66+
67+
private static String getDiscriminatorValue(JsonElement readElement, String discriminatorField) {
68+
JsonElement element = readElement.getAsJsonObject().get(discriminatorField);
69+
if(null == element) {
70+
throw new IllegalArgumentException("missing discriminator field: <" + discriminatorField + ">");
71+
}
72+
return element.getAsString();
73+
}
74+
75+
private static Class getClassByDiscriminator(Map classByDiscriminatorValue, String discriminatorValue) {
76+
Class clazz = (Class) classByDiscriminatorValue.get(discriminatorValue.toUpperCase());
77+
if(null == clazz) {
78+
throw new IllegalArgumentException("cannot determine model class of name: <" + discriminatorValue + ">");
79+
}
80+
return clazz;
81+
}
82+
4283
public JSON() {
43-
gson = new GsonBuilder()
84+
gson = createGson()
4485
.registerTypeAdapter(Date.class, dateTypeAdapter)
4586
.registerTypeAdapter(java.sql.Date.class, sqlDateTypeAdapter)
4687
.registerTypeAdapter(OffsetDateTime.class, offsetDateTimeTypeAdapter)

0 commit comments

Comments
 (0)