Skip to content

Commit cf610d6

Browse files
author
shenwen.yin
committed
feat: support explictly null set in model(poc)
1 parent 47fd3b0 commit cf610d6

File tree

5 files changed

+253
-46
lines changed

5 files changed

+253
-46
lines changed
+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.smartx.tower;
2+
3+
import com.google.gson.Gson;
4+
import com.google.gson.GsonBuilder;
5+
import com.smartx.tower.ApiClient;
6+
import com.smartx.tower.ApiException;
7+
import com.smartx.tower.ClientUtil;
8+
import com.smartx.tower.JSON;
9+
import com.smartx.tower.TaskUtil;
10+
import com.smartx.tower.api.BrickTopoApi;
11+
import com.smartx.tower.api.ContentLibraryVmTemplateApi;
12+
import com.smartx.tower.api.MetricsApi;
13+
import com.smartx.tower.api.VmApi;
14+
import com.smartx.tower.api.VmDiskApi;
15+
import com.smartx.tower.model.*;
16+
import java.io.IOException;
17+
import java.util.List;
18+
import java.util.ArrayList;
19+
import java.util.stream.Collectors;
20+
import java.util.Objects;
21+
22+
public class App {
23+
public static void main(String[] args) throws ApiException, IOException {
24+
test();
25+
}
26+
27+
public static void test() throws ApiException, IOException {
28+
VmUpdateHostOptionsParams params = new VmUpdateHostOptionsParams();
29+
VmUpdateHostOptionsParamsData data = new VmUpdateHostOptionsParamsData();
30+
data.hostname(null).presentDnsServers();
31+
params.setData(data);
32+
Gson gson = new JSON().getGson();
33+
System.out.println(gson.toJson(data));
34+
System.out.println(gson.toJson(params));
35+
VmUpdateHostOptionsParamsData data2 = gson.fromJson("{\"dns_servers\":[\"114.114.114.114\"]}",
36+
VmUpdateHostOptionsParamsData.class);
37+
VmUpdateHostOptionsParams params2 = gson.fromJson("{\"data\":{\"dns_servers\":[\"114.114.114.114\"]}}",
38+
VmUpdateHostOptionsParams.class);
39+
System.out.println(data2);
40+
System.out.println(params2);
41+
}
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package com.smartx.tower;
2+
3+
import java.lang.reflect.Field;
4+
import java.util.HashMap;
5+
import java.util.HashSet;
6+
import java.util.Map;
7+
import java.util.Set;
8+
9+
import com.google.gson.Gson;
10+
import com.google.gson.JsonElement;
11+
import com.google.gson.JsonObject;
12+
import com.google.gson.TypeAdapter;
13+
import com.google.gson.TypeAdapterFactory;
14+
import com.google.gson.annotations.SerializedName;
15+
import com.google.gson.reflect.TypeToken;
16+
import com.google.gson.stream.JsonReader;
17+
import com.google.gson.stream.JsonWriter;
18+
19+
public class ConditionalNullable {
20+
private final static String IS_PRESENT = "_isPresent_";
21+
22+
public static class ConditionalNullablePojo {
23+
protected Set<String> _isPresent_ = new HashSet<String>();
24+
}
25+
26+
public static class ConditionalNullablePojoAdapterFactory implements TypeAdapterFactory {
27+
@Override
28+
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
29+
Class<? super T> rawType = type.getRawType();
30+
if (!ConditionalNullablePojo.class.isAssignableFrom(rawType)) {
31+
return null;
32+
}
33+
Map<String, Field> jsonField = new HashMap<>();
34+
Field[] fields = rawType.getDeclaredFields();
35+
for (int i = 0; i < fields.length; i++) {
36+
Field field = fields[i];
37+
if (field.isAnnotationPresent(SerializedName.class)) {
38+
jsonField.put(field.getAnnotation(SerializedName.class).value(), field);
39+
}
40+
}
41+
return new TypeAdapter<T>() {
42+
@Override
43+
public void write(JsonWriter out, T value)
44+
throws java.io.IOException {
45+
if (value == null) {
46+
out.nullValue();
47+
return;
48+
}
49+
out.beginObject();
50+
ConditionalNullablePojo pojo = (ConditionalNullablePojo) value;
51+
// TypeAdapter<JsonElement> elementAdapter = gson.getAdapter(JsonElement.class);
52+
for (Map.Entry<String, Field> entry : jsonField.entrySet()) {
53+
String fieldName = entry.getKey();
54+
Field field = entry.getValue();
55+
// get the value of the field
56+
Object fieldValue;
57+
try {
58+
// mostly the field is private, so we need to make it accessible
59+
if (!field.canAccess(value)) {
60+
field.setAccessible(true);
61+
}
62+
fieldValue = field.get(value);
63+
} catch (IllegalArgumentException | IllegalAccessException e) {
64+
fieldValue = null;
65+
}
66+
if (fieldValue == null) {
67+
if (pojo._isPresent_.contains(fieldName)) {
68+
out.name(fieldName);
69+
if (!out.getSerializeNulls()) {
70+
out.setSerializeNulls(true);
71+
out.nullValue();
72+
out.setSerializeNulls(false);
73+
} else {
74+
out.nullValue();
75+
}
76+
}
77+
} else {
78+
// write the non null field with native adapter
79+
out.name(fieldName);
80+
@SuppressWarnings("unchecked")
81+
TypeAdapter<Object> delegatedAdapter = (TypeAdapter<Object>) gson
82+
.getAdapter(field.getType());
83+
if (delegatedAdapter != null && fieldValue != null) {
84+
delegatedAdapter.write(out, fieldValue);
85+
}
86+
}
87+
}
88+
out.endObject();
89+
}
90+
91+
public T read(JsonReader in) throws java.io.IOException {
92+
JsonObject jsonObject = gson.getAdapter(JsonElement.class).read(in).getAsJsonObject();
93+
T instance = gson.getDelegateAdapter(ConditionalNullablePojoAdapterFactory.this, type)
94+
.fromJsonTree(jsonObject);
95+
return instance;
96+
}
97+
};
98+
}
99+
}
100+
}

src/main/java/com/smartx/tower/JSON.java

+23-16
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,7 @@ public class JSON {
3939

4040
@SuppressWarnings("unchecked")
4141
public static GsonBuilder createGson() {
42-
GsonFireBuilder fireBuilder = new GsonFireBuilder()
43-
;
42+
GsonFireBuilder fireBuilder = new GsonFireBuilder();
4443
GsonBuilder builder = fireBuilder.createGsonBuilder();
4544
return builder;
4645
}
@@ -54,10 +53,13 @@ private static String getDiscriminatorValue(JsonElement readElement, String disc
5453
}
5554

5655
/**
57-
* Returns the Java class that implements the OpenAPI schema for the specified discriminator value.
56+
* Returns the Java class that implements the OpenAPI schema for the specified
57+
* discriminator value.
5858
*
59-
* @param classByDiscriminatorValue The map of discriminator values to Java classes.
60-
* @param discriminatorValue The value of the OpenAPI discriminator in the input data.
59+
* @param classByDiscriminatorValue The map of discriminator values to Java
60+
* classes.
61+
* @param discriminatorValue The value of the OpenAPI discriminator in
62+
* the input data.
6163
* @return The Java class that implements the OpenAPI schema
6264
*/
6365
private static Class getClassByDiscriminator(Map classByDiscriminatorValue, String discriminatorValue) {
@@ -70,12 +72,13 @@ private static Class getClassByDiscriminator(Map classByDiscriminatorValue, Stri
7072

7173
public JSON() {
7274
gson = createGson()
73-
.registerTypeAdapter(Date.class, dateTypeAdapter)
74-
.registerTypeAdapter(java.sql.Date.class, sqlDateTypeAdapter)
75-
.registerTypeAdapter(OffsetDateTime.class, offsetDateTimeTypeAdapter)
76-
.registerTypeAdapter(LocalDate.class, localDateTypeAdapter)
77-
.registerTypeAdapter(byte[].class, byteArrayAdapter)
78-
.create();
75+
.registerTypeAdapter(Date.class, dateTypeAdapter)
76+
.registerTypeAdapter(java.sql.Date.class, sqlDateTypeAdapter)
77+
.registerTypeAdapter(OffsetDateTime.class, offsetDateTimeTypeAdapter)
78+
.registerTypeAdapter(LocalDate.class, localDateTypeAdapter)
79+
.registerTypeAdapter(byte[].class, byteArrayAdapter)
80+
.registerTypeAdapterFactory(new ConditionalNullable.ConditionalNullablePojoAdapterFactory())
81+
.create();
7982
}
8083

8184
/**
@@ -103,7 +106,8 @@ public JSON setGson(Gson gson) {
103106
*
104107
* @param lenientOnJson Set it to true to ignore some syntax errors
105108
* @return JSON
106-
* @see <a href="https://www.javadoc.io/doc/com.google.code.gson/gson/2.8.5/com/google/gson/stream/JsonReader.html">https://www.javadoc.io/doc/com.google.code.gson/gson/2.8.5/com/google/gson/stream/JsonReader.html</a>
109+
* @see <a href=
110+
* "https://www.javadoc.io/doc/com.google.code.gson/gson/2.8.5/com/google/gson/stream/JsonReader.html">https://www.javadoc.io/doc/com.google.code.gson/gson/2.8.5/com/google/gson/stream/JsonReader.html</a>
107111
*/
108112
public JSON setLenientOnJson(boolean lenientOnJson) {
109113
isLenientOnJson = lenientOnJson;
@@ -133,7 +137,8 @@ public <T> T deserialize(String body, Type returnType) {
133137
try {
134138
if (isLenientOnJson) {
135139
JsonReader jsonReader = new JsonReader(new StringReader(body));
136-
// see https://www.javadoc.io/doc/com.google.code.gson/gson/2.8.5/com/google/gson/stream/JsonReader.html
140+
// see
141+
// https://www.javadoc.io/doc/com.google.code.gson/gson/2.8.5/com/google/gson/stream/JsonReader.html
137142
jsonReader.setLenient(true);
138143
return gson.fromJson(jsonReader, returnType);
139144
} else {
@@ -215,7 +220,7 @@ public OffsetDateTime read(JsonReader in) throws IOException {
215220
default:
216221
String date = in.nextString();
217222
if (date.endsWith("+0000")) {
218-
date = date.substring(0, date.length()-5) + "Z";
223+
date = date.substring(0, date.length() - 5) + "Z";
219224
}
220225
return OffsetDateTime.parse(date, formatter);
221226
}
@@ -282,7 +287,8 @@ public static class SqlDateTypeAdapter extends TypeAdapter<java.sql.Date> {
282287

283288
private DateFormat dateFormat;
284289

285-
public SqlDateTypeAdapter() {}
290+
public SqlDateTypeAdapter() {
291+
}
286292

287293
public SqlDateTypeAdapter(DateFormat dateFormat) {
288294
this.dateFormat = dateFormat;
@@ -335,7 +341,8 @@ public static class DateTypeAdapter extends TypeAdapter<Date> {
335341

336342
private DateFormat dateFormat;
337343

338-
public DateTypeAdapter() {}
344+
public DateTypeAdapter() {
345+
}
339346

340347
public DateTypeAdapter(DateFormat dateFormat) {
341348
this.dateFormat = dateFormat;

src/main/java/com/smartx/tower/model/VmUpdateHostOptionsParams.java

+11-14
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import com.google.gson.annotations.SerializedName;
88
import com.google.gson.stream.JsonReader;
99
import com.google.gson.stream.JsonWriter;
10+
import com.smartx.tower.ConditionalNullable;
1011
import com.smartx.tower.model.VmUpdateHostOptionsParamsData;
1112
import com.smartx.tower.model.VmWhereInput;
1213
import io.swagger.annotations.ApiModel;
@@ -17,7 +18,7 @@
1718
* VmUpdateHostOptionsParams
1819
*/
1920
@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaSmartxClientCodegen")
20-
public class VmUpdateHostOptionsParams {
21+
public class VmUpdateHostOptionsParams extends ConditionalNullable.ConditionalNullablePojo {
2122
public static final String SERIALIZED_NAME_DATA = "data";
2223
@SerializedName(SERIALIZED_NAME_DATA)
2324
private VmUpdateHostOptionsParamsData data;
@@ -26,55 +27,53 @@ public class VmUpdateHostOptionsParams {
2627
@SerializedName(SERIALIZED_NAME_WHERE)
2728
private VmWhereInput where;
2829

29-
public VmUpdateHostOptionsParams() {
30+
public VmUpdateHostOptionsParams() {
3031
}
3132

3233
public VmUpdateHostOptionsParams data(VmUpdateHostOptionsParamsData data) {
33-
34+
3435
this.data = data;
3536
return this;
3637
}
3738

38-
/**
39+
/**
3940
* Get data
41+
*
4042
* @return data
41-
**/
43+
**/
4244
@javax.annotation.Nonnull
4345
@ApiModelProperty(required = true, value = "")
4446

4547
public VmUpdateHostOptionsParamsData getData() {
4648
return data;
4749
}
4850

49-
5051
public void setData(VmUpdateHostOptionsParamsData data) {
5152
this.data = data;
5253
}
5354

54-
5555
public VmUpdateHostOptionsParams where(VmWhereInput where) {
56-
56+
5757
this.where = where;
5858
return this;
5959
}
6060

61-
/**
61+
/**
6262
* Get where
63+
*
6364
* @return where
64-
**/
65+
**/
6566
@javax.annotation.Nonnull
6667
@ApiModelProperty(required = true, value = "")
6768

6869
public VmWhereInput getWhere() {
6970
return where;
7071
}
7172

72-
7373
public void setWhere(VmWhereInput where) {
7474
this.where = where;
7575
}
7676

77-
7877
@Override
7978
public boolean equals(Object o) {
8079
if (this == o) {
@@ -113,6 +112,4 @@ private String toIndentedString(Object o) {
113112
}
114113
return o.toString().replace("\n", "\n ");
115114
}
116-
117115
}
118-

0 commit comments

Comments
 (0)