Skip to content

Commit df7e6fb

Browse files
authored
Merge pull request #237 from jwfing/master
fixed #236
2 parents ffd8381 + a5ede3f commit df7e6fb

22 files changed

+250
-47
lines changed

CHANGELOG.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,18 @@ Following is change logs for recently release versions, you can refer to [releas
55
> Warning:
66
> DONOT upgrade java-websocket to 1.15.0(or above), bcz it doesn't work on Android 5.1 or earlier version.
77
8+
## 8.2.19 release
9+
10+
#### Break changes
11+
- None
12+
13+
#### New features
14+
- None
15+
16+
#### Optimization and fixed bugs
17+
- fixed: correct json parser for LCFile#save with prefix path(GameSave doesn't work in version 8.2.16-18).
18+
19+
820
## 8.2.18 release
921

1022
#### Break changes
@@ -16,6 +28,7 @@ Following is change logs for recently release versions, you can refer to [releas
1628
#### Optimization and fixed bugs
1729
- fixed: correct json field name for captcha validation result.
1830

31+
1932
## 8.2.17 release
2033

2134
#### Break changes
@@ -27,6 +40,7 @@ Following is change logs for recently release versions, you can refer to [releas
2740
#### Optimization and fixed bugs
2841
- fixed: let query callback run in main thread for CACHE_THEN_NETWORK policy.
2942

43+
3044
## 8.2.16 release
3145

3246
#### Break changes
@@ -40,6 +54,7 @@ Following is change logs for recently release versions, you can refer to [releas
4054
- change Gson type adapter for some classes, avoid to use internal tools;
4155
- other optimizations.
4256

57+
4358
## 8.2.15 release
4459

4560
#### Break changes

android-sdk/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ allprojects {
3232
}
3333

3434
ext {
35-
sdkVersion = "8.2.18"
35+
sdkVersion = "8.2.19"
3636
supportLibVersion = "26.1.0"
3737
converterVersion = "2.1.0"
3838
rxandroidVersion = "2.1.1"

android-sdk/gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ org.gradle.jvmargs=-Xmx1536m
1515
# This option should only be used with decoupled projects. More details, visit
1616
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
1717
# org.gradle.parallel=true
18-
VERSION_NAME=8.2.18
18+
VERSION_NAME=8.2.19
1919
VERSION_CODE=2695
2020
GROUP=cn.leancloud
2121

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package cn.leancloud.annotation;
2+
3+
import java.lang.annotation.ElementType;
4+
import java.lang.annotation.Retention;
5+
import java.lang.annotation.RetentionPolicy;
6+
import java.lang.annotation.Target;
7+
8+
@Retention(RetentionPolicy.RUNTIME)
9+
@Target({ElementType.FIELD})
10+
public @interface JsonField {
11+
String value();
12+
}

core/src/main/java/cn/leancloud/gson/BaseOperationAdapter.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import com.google.gson.JsonElement;
1111
import com.google.gson.JsonObject;
1212
import com.google.gson.TypeAdapter;
13-
import com.google.gson.internal.bind.TypeAdapters;
1413
import com.google.gson.stream.JsonReader;
1514
import com.google.gson.stream.JsonWriter;
1615

@@ -36,11 +35,13 @@ public void write(JsonWriter writer, BaseOperation op) throws IOException {
3635
List<ObjectFieldOperation> subOps = ((CompoundOperation)op).getSubOperations();
3736
jsonObject.add(ATTR_SUBOPS, GsonWrapper.toJsonElement(subOps));
3837
}
39-
TypeAdapters.JSON_ELEMENT.write(writer, jsonObject);
38+
TypeAdapter<JsonElement> elementAdapter = GsonWrapper.getAdapter(JsonElement.class);
39+
elementAdapter.write(writer, jsonObject);
4040
}
4141

4242
public BaseOperation read(JsonReader reader) throws IOException {
43-
JsonElement elem = TypeAdapters.JSON_ELEMENT.read(reader);
43+
TypeAdapter<JsonElement> elementAdapter = GsonWrapper.getAdapter(JsonElement.class);
44+
JsonElement elem = elementAdapter.read(reader);
4445
if (elem.isJsonObject()) {
4546
JsonObject jsonObject = elem.getAsJsonObject();
4647
return parseJSONObject(new GsonObject(jsonObject));

core/src/main/java/cn/leancloud/gson/FileUploadTokenAdapter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import com.google.gson.stream.JsonWriter;
88

99
import java.io.IOException;
10-
10+
@Deprecated
1111
public class FileUploadTokenAdapter extends TypeAdapter<FileUploadToken> {
1212
private static final String FIELD_BUCKET = "bucket";
1313
private static final String FIELD_OBJECTID = "objectId";

core/src/main/java/cn/leancloud/gson/GSONParser.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import cn.leancloud.json.JSONParser;
66
import cn.leancloud.json.TypeReference;
77
import com.google.gson.JsonArray;
8-
import com.google.gson.JsonObject;
98

109
import java.util.ArrayList;
1110
import java.util.List;

core/src/main/java/cn/leancloud/gson/GeneralFieldMappingObjectAdapter.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@
1111
import java.lang.reflect.Type;
1212
import java.util.*;
1313

14+
/**
15+
* deprecated since 8.2.19.
16+
* @param <T> generic type.
17+
*/
18+
19+
@Deprecated
1420
public class GeneralFieldMappingObjectAdapter<T> extends TypeAdapter<T> {
1521
private Class targetClazz;
1622
private Map<String, Type> displayFields;
@@ -90,6 +96,7 @@ public T read(JsonReader jsonReader) throws IOException {
9096
try {
9197
Field field = result.getClass().getDeclaredField(identifyFieldName);
9298
if (null == valueType || null == field) {
99+
jsonReader.skipValue();
93100
continue;
94101
}
95102
field.setAccessible(true);
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
package cn.leancloud.gson;
2+
3+
import cn.leancloud.annotation.JsonField;
4+
import com.google.gson.TypeAdapter;
5+
import com.google.gson.stream.JsonReader;
6+
import com.google.gson.stream.JsonToken;
7+
import com.google.gson.stream.JsonWriter;
8+
9+
import java.io.IOException;
10+
import java.lang.reflect.Field;
11+
import java.lang.reflect.Type;
12+
import java.util.HashMap;
13+
import java.util.Map;
14+
15+
public class GeneralSimpleObjectAdapter<T> extends TypeAdapter<T> {
16+
private Class targetClazz;
17+
private Map<String, Field> displayFields = new HashMap<>();
18+
19+
public GeneralSimpleObjectAdapter(Class clazz) {
20+
this.targetClazz = clazz;
21+
Field[] fields = clazz.getDeclaredFields();
22+
for (Field field: fields) {
23+
String fieldName = field.getName();
24+
JsonField annotation = field.getAnnotation(JsonField.class);
25+
if (null != annotation) {
26+
fieldName = annotation.value();
27+
}
28+
displayFields.put(fieldName, field);
29+
}
30+
}
31+
@Override
32+
public void write(JsonWriter jsonWriter, T t) throws IOException {
33+
jsonWriter.beginObject();
34+
Field[] fields = t.getClass().getDeclaredFields();
35+
for(Field field : fields) {
36+
field.setAccessible(true);
37+
String canonicalName = field.getName();
38+
String outputName = canonicalName;
39+
JsonField jsonField = field.getAnnotation(JsonField.class);
40+
if (null != jsonField) {
41+
outputName = jsonField.value();
42+
}
43+
Type valueType = field.getType();
44+
try {
45+
if (valueType.equals(Character.class) || valueType.equals(char.class)) {
46+
char value = field.getChar(t);
47+
jsonWriter.name(outputName).value(value);
48+
} else if (valueType.equals(Boolean.class) || valueType.equals(boolean.class)) {
49+
boolean value = field.getBoolean(t);
50+
jsonWriter.name(outputName).value(value);
51+
} else if (valueType.equals(String.class)) {
52+
String value = (String)field.get(t);
53+
jsonWriter.name(outputName).value(value);
54+
} else if (valueType.equals(Integer.class) || valueType.equals(int.class)) {
55+
Integer value = (Integer) field.get(t);
56+
jsonWriter.name(outputName).value(value);
57+
} else if (valueType.equals(Long.class) || valueType.equals(long.class)) {
58+
Long value = (Long) field.get(t);
59+
jsonWriter.name(outputName).value(value);
60+
} else if (valueType.equals(Float.class) || valueType.equals(float.class)) {
61+
Float value = (Float) field.get(t);
62+
jsonWriter.name(outputName).value(value);
63+
} else if (valueType.equals(Double.class) || valueType.equals(double.class)) {
64+
Double value = (Double) field.get(t);
65+
jsonWriter.name(outputName).value(value);
66+
}
67+
} catch (Exception ex) {
68+
ex.printStackTrace();
69+
}
70+
}
71+
jsonWriter.endObject();
72+
jsonWriter.flush();
73+
}
74+
75+
@Override
76+
public T read(JsonReader jsonReader) throws IOException {
77+
try {
78+
T result = (T)this.targetClazz.newInstance();
79+
jsonReader.beginObject();
80+
String jsonFieldName = null;
81+
while(jsonReader.hasNext()) {
82+
JsonToken token = jsonReader.peek();
83+
if (token.equals(JsonToken.NAME)) {
84+
// get current token.
85+
jsonFieldName = jsonReader.nextName();
86+
}
87+
Field targetField = this.displayFields.get(jsonFieldName);
88+
// move to next token
89+
jsonReader.peek();
90+
try {
91+
if (null == targetField) {
92+
jsonReader.skipValue();
93+
continue;
94+
}
95+
targetField.setAccessible(true);
96+
Object value = null;
97+
Type valueType = targetField.getType();
98+
if (valueType.equals(String.class)) {
99+
value = jsonReader.nextString();
100+
} else if (valueType.equals(Integer.class) || valueType.equals(int.class)) {
101+
value = jsonReader.nextInt();
102+
} else if (valueType.equals(Boolean.class) || valueType.equals(boolean.class)) {
103+
value = jsonReader.nextBoolean();
104+
} else if (valueType.equals(Character.class) || valueType.equals(char.class)) {
105+
value = jsonReader.nextString();
106+
} else if (valueType.equals(Long.class) || valueType.equals(long.class)) {
107+
value = jsonReader.nextLong();
108+
} else if (valueType.equals(Float.class) || valueType.equals(float.class)) {
109+
value = jsonReader.nextDouble();
110+
} else if (valueType.equals(Double.class) || valueType.equals(double.class)) {
111+
value = jsonReader.nextDouble();
112+
} else {
113+
jsonReader.skipValue();
114+
}
115+
if (null != value) {
116+
targetField.set(result, value);
117+
}
118+
} catch (Exception ex) {
119+
ex.printStackTrace();
120+
}
121+
}
122+
jsonReader.endObject();
123+
return result;
124+
} catch (InstantiationException e) {
125+
throw new RuntimeException(e);
126+
} catch (IllegalAccessException e) {
127+
throw new RuntimeException(e);
128+
}
129+
}
130+
}

core/src/main/java/cn/leancloud/gson/GsonWrapper.java

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
import cn.leancloud.sms.LCCaptchaDigest;
88
import cn.leancloud.sms.LCCaptchaValidateResult;
99
import cn.leancloud.upload.FileUploadToken;
10+
import cn.leancloud.utils.LCUtils;
1011
import com.google.gson.*;
11-
import com.google.gson.internal.Primitives;
1212
import com.google.gson.reflect.TypeToken;
1313

1414
import java.lang.reflect.Modifier;
@@ -23,21 +23,6 @@ public class GsonWrapper {
2323
static final BaseOperationAdapter baseOperationAdapter = new BaseOperationAdapter();
2424
static final JSONObjectAdapter jsonObjectAdapter = new JSONObjectAdapter();
2525
static final JSONArrayAdapter jsonArrayAdapter = new JSONArrayAdapter();
26-
static final Map<String, Type> appAccessEndpointFields = new HashMap<String, Type>() {{
27-
put("ttl", Long.class);
28-
put("stats_server", String.class);
29-
put("push_server", String.class);
30-
put("rtm_router_server", String.class);
31-
put("api_server", String.class);
32-
put("engine_server", String.class);
33-
}};
34-
static final Map<String, Type> captchaDigestFields = new HashMap<String, Type>() {{
35-
put("captcha_token", String.class);
36-
put("captcha_url", String.class);
37-
}};
38-
static final Map<String, Type> captchaValidateResultFields = new HashMap<String, Type>() {{
39-
put("validate_token", String.class);
40-
}};
4126

4227
static final Gson gson = new GsonBuilder().serializeNulls()
4328
.excludeFieldsWithModifiers(Modifier.STATIC, Modifier.TRANSIENT, Modifier.VOLATILE)
@@ -68,16 +53,14 @@ public class GsonWrapper {
6853
.registerTypeAdapter(JSONObject.class, jsonObjectAdapter)
6954
.registerTypeAdapter(GsonArray.class, jsonArrayAdapter)
7055
.registerTypeAdapter(Date.class, new GsonUTCDateAdapter())
71-
.registerTypeAdapter(FileUploadToken.class, new FileUploadTokenAdapter())
56+
.registerTypeAdapter(FileUploadToken.class,
57+
new GeneralSimpleObjectAdapter<FileUploadToken>(FileUploadToken.class))
7258
.registerTypeAdapter(AppAccessEndpoint.class,
73-
new GeneralFieldMappingObjectAdapter<AppAccessEndpoint>(AppAccessEndpoint.class,
74-
appAccessEndpointFields, FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES ))
59+
new GeneralSimpleObjectAdapter<AppAccessEndpoint>(AppAccessEndpoint.class))
7560
.registerTypeAdapter(LCCaptchaDigest.class,
76-
new GeneralFieldMappingObjectAdapter<LCCaptchaDigest>(LCCaptchaDigest.class,
77-
captchaDigestFields, FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES))
61+
new GeneralSimpleObjectAdapter<LCCaptchaDigest>(LCCaptchaDigest.class))
7862
.registerTypeAdapter(LCCaptchaValidateResult.class,
79-
new GeneralFieldMappingObjectAdapter<LCCaptchaValidateResult>(LCCaptchaValidateResult.class,
80-
captchaValidateResultFields, FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES))
63+
new GeneralSimpleObjectAdapter<LCCaptchaValidateResult>(LCCaptchaValidateResult.class))
8164
.registerTypeAdapter(new TypeToken<Map<String, Object>>(){}.getType(), new MapDeserializerDoubleAsIntFix())
8265
.registerTypeAdapter(Map.class, new MapDeserializerDoubleAsIntFix())
8366
.setLenient()
@@ -94,6 +77,10 @@ public static String toJsonString(Map<String, Object> map) {
9477
return gson.toJson(map);
9578
}
9679

80+
public static <T> TypeAdapter<T> getAdapter(Class<T> clazz) {
81+
return gson.getAdapter(clazz);
82+
}
83+
9784
public static JsonElement toJsonElement(Object object) {
9885
if (null == object) {
9986
return null;
@@ -143,7 +130,7 @@ public static <T> T parseObject(String jsonString, Class<T> clazz) {
143130
}
144131

145132
public static <T> T parseObject(String jsonString, Type typeOfT) {
146-
if (Primitives.isPrimitive(typeOfT)
133+
if (LCUtils.isPrimitive(typeOfT)
147134
|| (typeOfT instanceof Class && String.class.isAssignableFrom((Class)typeOfT))) {
148135
JsonElement element = gson.toJsonTree(jsonString, typeOfT);
149136
return gson.fromJson(element, typeOfT);

0 commit comments

Comments
 (0)