
一、背景
移动端大多情况下与server交互使用的都是json数据,Android 主要基于Java语言(是一种强类型语言),一些公司server端使用的是php语言(属于弱类型语言),而在一些情形下,server端返回的数据格式 和 我们定义的数据格式不一致,这样可能导致以几个结果 :
- 程序崩溃
- 中断解析
- 返回默值继续解析
可能有的同学觉得这是server端的问题,我们没有必要处理,遇到问题后让服务端处理就好了,但是有没有想过,server端返回的某个字段对于我们来说,可能就是页面上某个文案的显示与否,而客户端不处理的结果就是导致程序崩溃,在这个时段,这个功能下所有用户都无法使用,这会造成很不好的用户体验。当然 server 也必须确保 我们统一协定的 的json格式和数据类型没有问题,即数据源没有问题,否则功能会受影响。
现在市场上有很多的 json 解析工具,如阿里的fastjson、Google 的 Gson 等 ,这里我们主要基于Google的 Gson 进行封装
二、功能描述
1、支持解析OBJECT{}、ARRAY[]、Map、String、基本数据类型等 在 异常情况下, 解析到 正常数据 或者 处理为 默认值
- 一行代码实现数据的系列化或反系列化
- 当某个字段解析失败后,可跳转下一个字段继续解析,至少可保证部分功能 可以正常使用
- 某个字段解析失败后,给默认值,如果是基本数据类型,如int,则默认值为0,boolean默认值为false,如果是array类型,默认为[],即空集合
- 某些异常数据可正常解析,如服务端某个字段的值是一个经过转义的json,即是一个字符串,可正常解析成对OBJECT或者ARRAY,再比如说我们要的是String ,而服务端返回了Object 或ARRAY ,会将Object或者ARRAY的数据 装到 JsonObject或者JsonArray中,然后toString 赋值给我们要的String 字段,即获取到我们想要的数据
2、详细的demo及使用方式 请查看 github连接
3、支持的情况说明
-
client 要{}, server 给了 []、空字符串、字符串、数字、boolean, 均返回实例对象{},为空对象,length为0
- 即使服务端给返回一个转义的json串,只要满足{},也可解析
- 传入非标准json格式、传入html的格式或其它非json格式,会直接报异常 JsonSyntaxException
-
client要[],server端给了 {}、空字符串、字符串、数字、boolean,均返回空数组[] ,length 为0
- toObjectArray,传入非标准json格式、传入html的格式或其它非json格式,不会报异常,会直接返回[]
- toArraysList,如果数据格式不是[],会报异常,使用时请关注
- 即使服务端给返回一个转义的json串,只要满足[],也可解析
-
client 要byte.class,Byte.class,int.class, Integer.class,short.class, Short.class,long.class, Long.class,double.class, Double.class, float.class, Float.class 等情况
- server 给的非数字类型,如空字符串、字符串、boolean、array、object 等,解析返回0;
- server 给的数据 超过 实际类型 的取值范围,如定义int ,值不能超过 2147483647 ,超过解析返回0,所以定义类型时一定考虑数据的取值范围;
- client 要int/short/long,server 给的float/double,解析返回0,所以服务端经的数据可能为浮点类型时,最好使用float或者double
-
client 要String类型
- 如果server给了[]/{},则返回""
- 如果server给了[]或者{}里面有数据,即会解析返回实际的字符串,该string是经过转义的json串
- 如果server给了基本数据类型或者boolean类型,则会将其转成String类型
-
client 要map对象 ,server 给了[]、空字符串、字符串、boolean、数字,解析均返回实例对象{} ,即空map集合
-
要boolean,服务端给byte/int/short/long/float/double/array/object/字符串,解析返回false,字符串true ,会返回true
-
目前已知的三种崩溃情况
- 解析时传入xml
- 解析时传入一个字符串
- 解析时传入一个非标准的json数据
- 不支持app使用char类型,原因是json格式中的数据必须是String 或者Number
三、源码解析
1、通过反射获取到ConstructorConstructor 中instanceCreators 实例 ,就可能通 GsonBuilder 注册各种类型的适配器,如byte/short/ int /long /float/double/boolean/string/map /array/object 等,通过这些自定义的适配器,我们就能针对其做定制,将某些不合法的数据处理成我们需要的数据,一般是对应类型的默认值
private static Gson newGson() {
GsonBuilder gsonBuilder = new GsonBuilder();
Class builder = (Class) gsonBuilder.getClass();
Field f = null;
try {
//通过反射得到构造器
f = builder.getDeclaredField("instanceCreators");
f.setAccessible(true);
final Map<Type, InstanceCreator<?>> val = (Map<Type, InstanceCreator<?>>) f.get(gsonBuilder);//得到此属性的值
//注册Char类型处理器
// gsonBuilder.registerTypeAdapterFactory(TypeAdapters.newFactory(char.class, Character.class, GsonUtils.charTypeAdapter()));
//注册String类型处理器
gsonBuilder.registerTypeAdapterFactory(TypeAdapters.newFactory(String.class, GsonUtils.stringTypeAdapter()));
//注册int.class, Integer.class处理器
gsonBuilder.registerTypeAdapterFactory(TypeAdapters.newFactory(byte.class, Byte.class, GsonUtils.longAdapter(GsonUtils.OBJECT_TYPE_BYTE)));
//注册short.class, Short.class处理器
gsonBuilder.registerTypeAdapterFactory(TypeAdapters.newFactory(short.class, Short.class, GsonUtils.longAdapter(GsonUtils.OBJECT_TYPE_SHORT)));
//注册int.class, Integer.class处理器
gsonBuilder.registerTypeAdapterFactory(TypeAdapters.newFactory(int.class, Integer.class, GsonUtils.longAdapter(GsonUtils.OBJECT_TYPE_INT)));
//注册long.class, Long.class处理器
gsonBuilder.registerTypeAdapterFactory(TypeAdapters.newFactory(long.class, Long.class, GsonUtils.longAdapter(GsonUtils.OBJECT_TYPE_LONG)));
//注册double.class, Double.class处理器
gsonBuilder.registerTypeAdapterFactory(TypeAdapters.newFactory(double.class, Double.class, GsonUtils.longAdapter(GsonUtils.OBJECT_TYPE_DOUBLE)));
//注册float.class, Float.class处理器
gsonBuilder.registerTypeAdapterFactory(TypeAdapters.newFactory(float.class, Float.class, GsonUtils.longAdapter(GsonUtils.OBJECT_TYPE_FLOAT)));
//注册boolean.class,Boolean.class处理器
gsonBuilder.registerTypeAdapterFactory(TypeAdapters.newFactory(boolean.class, Boolean.class, GsonUtils.booleanTypeAdapter()));
//注册反射对象的处理器
gsonBuilder.registerTypeAdapterFactory(
new ReflectiveTypeAdapterFactory(new ConstructorConstructor(val), FieldNamingPolicy.IDENTITY, Excluder.DEFAULT));
//注册集合的处理器
gsonBuilder.registerTypeAdapterFactory(new CollectionTypeAdapterFactory(new ConstructorConstructor(val)));
//支持Map的key为复杂对象的形式 ,如:Map<Point, String> map = new LinkedHashMap<Point, String>();
gsonBuilder.enableComplexMapKeySerialization();
//注册Map集合的处理器
gsonBuilder.registerTypeAdapterFactory(new MapTypeAdapterFactory(new ConstructorConstructor(val), true));
//对json结果格式化.
gsonBuilder.setPrettyPrinting();
} catch (Exception e) {
e.printStackTrace();
}
return gsonBuilder.create();
}
2、处理字符串的适配器,注释写的很详细,自己看吧
/**
* 处理字符的适配器
*/
public static TypeAdapter<String> stringTypeAdapter() {
return new TypeAdapter<String>() {
//反系列化操作
@Override
public String read(JsonReader in)
throws IOException {
JsonToken peek = in.peek();
// 增加判断是错误的NULL的类型,如果为NULL ,则反系列化为""
if (peek == JsonToken.NULL) {
in.nextNull();
return "";
}
//增加判断是错误的Boolean的类型,如果为Boolean ,则反系列化为 "boolean"
if (peek == JsonToken.BOOLEAN) {
return Boolean.toString(in.nextBoolean());
}
//
//增加判断是错误的name的类型,移动in的下标到结束,移动下标的代码在下方
if (in.peek() == JsonToken.NAME) {
in.nextName();
return "";
}
//增加判断是错误的object的类型
//如果是object类型,则会去解析这个object ,将数据放于JSONObject,再转成String返回
if (in.peek() == JsonToken.BEGIN_OBJECT) {
JSONObject j = readObject(in);
if(j==null||j.length()==0){
return "";
}
return j.toString();
// return StringEscapeUtils.unescapeJson(j.toString());
}
//增加判断是错误的ARRAY的类型
//如果是ARRAY类型,则会去解析这个ARRAY ,将数据放于JSONObject,再转成String返回
if (in.peek() == JsonToken.BEGIN_ARRAY) {
JSONArray j = readArray(in);
if(j==null||j.length()==0){
return "";
}
return j.toString();
// return StringEscapeUtils.unescapeJson(j.toString());
}
return in.nextString();
// return StringEscapeUtils.unescapeJson(in.nextString());
}
//系列化操作
@Override
public void write(JsonWriter out, String value)
throws IOException {
out.value(value);
}
};
}
3、 Number 类型的适配器,除了常见的数据类型错误兼容外,还包含了取值范围 不在 byte/int /short之内的处理,还有client 要的是byte/int/short/long ,server端返回了浮点类型(float/double)的情况,自己看代码吧,注释很详细
/**
* @param type
* public static final int OBJECT_TYPE_BYTE = 0;(short.class, Short.class)
* public static final int OBJECT_TYPE_SHORT = 1;(short.class, Short.class)
* public static final int OBJECT_TYPE_INT = 2;(int.class, Integer.class )
* public static final int OBJECT_TYPE_LONG = 3;(long.class,Long.class)
* public static final int OBJECT_TYPE_DOUBLE =4;(double.class, Double.class)
* public static final int OBJECT_TYPE_FLOAT = 5;(float.class, Float.class)
*
* @return TypeAdapter
*/
public static TypeAdapter<Number> longAdapter(final int type) {
return new TypeAdapter<Number>() {
//反系列化
@Override
public Number read(JsonReader in)
throws IOException {
//server端给的类型不对,则为true
boolean isNot = false;
if (in.peek() == JsonToken.NULL) {
// 增加判断是错误的NULL的类型
in.nextNull();
isNot = true;
} else if (in.peek() == JsonToken.BEGIN_OBJECT) {
//增加判断是错误OBJECT的类型(应该是Number),移动in的下标到结束,移动下标的代码在下方
readObject(in);
isNot = true;
} else if (in.peek() == JsonToken.NAME) {
//增加判断是错误的name的类型(应该是Number),移动in的下标到结束,移动下标的代码在下方
in.nextName();
isNot = true;
} else if (in.peek() == JsonToken.BOOLEAN) {
//增加判断是错误的boolean的类型(应该是Number),移动in的下标到结束,移动下标的代码在下方
in.nextBoolean();
isNot = true;
} else if (in.peek() == JsonToken.BEGIN_ARRAY) {
//增加判断是错误的array的类型(应该是Number),移动in的下标到结束,移动下标的代码在下方
readArray(in);
isNot = true;
}
//以上判断的几种错误类型,不对,则直接返回默认值
if (isNot) {
switch (type) {
case OBJECT_TYPE_BYTE:
return (byte)0;
case OBJECT_TYPE_SHORT:
return (short) 0;
case OBJECT_TYPE_INT:
return 0;
case OBJECT_TYPE_LONG:
return (long)0;
case OBJECT_TYPE_DOUBLE:
return (double) 0;
case OBJECT_TYPE_FLOAT:
return (float) 0;
default:
return 0;
}
}
try {
switch (type) {
case OBJECT_TYPE_BYTE:
//Byte
if (in.peek() == JsonToken.STRING) {
//暂不做处理
return toByte(in.nextString()).byteValue();
}else if(in.peek() == JsonToken.NUMBER){
//数字类型
// 判断是不是浮点类型,如果是则解析 返回0
String numberStr = in.nextString();
if (judgeDouble(numberStr)) {
return (byte) 0;
}
// 判断取值范围是否正确,如果不正确,则解析返回0
Long aLong = toLong(numberStr);
if(aLong.longValue()>BYTE_MAX||aLong<BYTE_MIN){
return (byte)0;
}
return (byte)aLong.longValue();
}
return (byte) in.nextInt();
case OBJECT_TYPE_SHORT:
//short
if (in.peek() == JsonToken.STRING) {
//暂不做处理
return toShort(in.nextString()).shortValue();
}else if(in.peek() == JsonToken.NUMBER){
//数字类型
// 判断是不是浮点类型,如果是则解析 返回0
String numberStr = in.nextString();
if (judgeDouble(numberStr)) {
return (short) 0;
}
// 判断取值范围是否正确,如果不正确,则解析返回0
Long aLong = toLong(numberStr);
if(aLong.longValue()>SHORT_MAX||aLong<SHORT_MIN){
return (short)0;
}
return (short)aLong.longValue();
}
return (short) in.nextInt();
case OBJECT_TYPE_INT:
//int
if (in.peek() == JsonToken.STRING) {
//暂不做处理
return toInt(in.nextString());
}else if(in.peek() == JsonToken.NUMBER){
//数字类型
// 判断是不是浮点类型,如果是则解析 返回0
String numberStr = in.nextString();
if (judgeDouble(numberStr)) {
return 0;
}
// 判断取值范围是否正确,如果不正确,则解析返回0
Long aLong = toLong(numberStr);
if(aLong.longValue()>INT_MAX||aLong<INT_MIN){
return 0;
}
return (int)aLong.longValue();
}
return in.nextInt();
case OBJECT_TYPE_LONG:
//long
if (in.peek() == JsonToken.STRING) {
//暂不做处理
return toLong(in.nextString()).longValue();
}else if(in.peek() == JsonToken.NUMBER){
//数字类型
// 判断是不是浮点类型,如果是则解析 返回0
String numberStr = in.nextString();
if (judgeDouble(numberStr)) {
return (long) 0;
}
// 判断取值范围是否正确,很大,这里不需要再判断了
Long aLong = toLong(numberStr);
return aLong.longValue();
}
return in.nextLong();
case OBJECT_TYPE_DOUBLE:
//double
if (in.peek() == JsonToken.STRING) {
//暂不做处理
return toDouble(in.nextString()).doubleValue();
}
return in.nextDouble();
case OBJECT_TYPE_FLOAT:
//float
if (in.peek() == JsonToken.STRING) {
//暂不做处理
return toFloat(in.nextString()).floatValue();
}
return (float) in.nextDouble();
}
return in.nextLong();
} catch (NumberFormatException e) {
throw new JsonSyntaxException(e);
}
}
//系列化
@Override
public void write(JsonWriter out, Number value)
throws IOException {
if (value == null) {
out.nullValue();
return;
}
out.value(value);
}
};
}
4、Boolean 类型的适配器,具体查看代码,应该是最简单的一个
/**
* boolean适配器
* @return
*/
public static TypeAdapter<Boolean> booleanTypeAdapter() {
return new TypeAdapter<Boolean>() {
@Override
public Boolean read(JsonReader in) throws IOException {
JsonToken peek = in.peek();
// 增加判断是错误的NULL的类型,如果为NULL ,则反系列化为false
if (peek == JsonToken.NULL) {
in.nextNull();
return false;
}
//增加判断是错误的name的类型(应该是boolean),移动in的下标到结束,移动下标的代码在下方
if (in.peek() == JsonToken.NAME) {
in.nextName();
return false;
}
//增加判断是错误的NUMBER的类型(应该是boolean),移动in的下标到结束,移动下标的代码在下方
if(in.peek() == JsonToken.NUMBER){
in.nextDouble();
return false;
}
//增加判断是错误的STRING的类型(应该是boolean),移动in的下标到结束,移动下标的代码在下方
if(in.peek() == JsonToken.STRING){
return Boolean.valueOf(in.nextString());
//return Boolean.parseBoolean(in.nextString());
}
//增加判断是错误的object的类型(应该是boolean),移动in的下标到结束,移动下标的代码在下方
if (in.peek() == JsonToken.BEGIN_OBJECT) {
readObject(in);
return false;
}
//增加判断是错误的array的类型(应该是boolean),移动in的下标到结束,移动下标的代码在下方
if (in.peek() == JsonToken.BEGIN_ARRAY) {
readArray(in);
return false;
}
return in.nextBoolean();
}
@Override
public void write(JsonWriter out, Boolean value) throws IOException {
out.value(value);
}
};
}
5、 Object 类型的适配器,将Gson中的ReflectiveTypeAdapterFactory 复制出来,修改适配器代码
public static final class Adapter<T> extends TypeAdapter<T> {
private final ObjectConstructor<T> constructor;
private final Map<String, BoundField> boundFields;
Adapter(ObjectConstructor<T> constructor, Map<String, BoundField> boundFields) {
this.constructor = constructor;
this.boundFields = boundFields;
}
@Override
public T read(JsonReader in) throws IOException {
//增加判断是错误的NULL的类型(应该是object),移动in的下标到结束,移动下标的代码在下方
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return constructor.construct();
}
//增加判断是错误的ARRAY的类型(应该是object),移动in的下标到结束,移动下标的代码在下方
if (in.peek() == JsonToken.BEGIN_ARRAY) {
GsonUtils.readArray(in);
return constructor.construct();
}
//增加判断是错误的NUMBER的类型(应该是object),移动in的下标到结束,移动下标的代码在下方
if (in.peek() == JsonToken.NUMBER) {
in.nextDouble();
return constructor.construct();
}
//增加判断是错误的String的类型(应该是object),移动in的下标到结束,移动下标的代码在下方
//如果给的object是一个转义的字符串,此处会单独处理解析返回
if (in.peek() == JsonToken.STRING) {
String value = in.nextString();
String path = in.getPath();
LogTagsUtils.i("===object====getPath:" + path.length() + "\nvalue:" + value);
//path的值一定会大于1,不大于1则为非json数据
if (path == null || path.length() <= 1) {
throw new IllegalStateException("格式异常");
}
//如果为字符串里的json满足定义的实体,也会解析
if (value.startsWith("{") && value.endsWith("}")) {
return (T) CommonJsonBuilder.fromJson(value, constructor.construct().getClass());
}
return constructor.construct();
}
//增加判断是错误的name的类型(应该是object),移动in的下标到结束,移动下标的代码在下方
if (in.peek() == JsonToken.NAME) {
in.nextName();
return constructor.construct();
}
//增加判断是错误的bookean的类型(应该是object),移动in的下标到结束,移动下标的代码在下方
if (in.peek() == JsonToken.BOOLEAN) {
in.nextBoolean();
return constructor.construct();
}
T instance = constructor.construct();
try {
in.beginObject();
while (in.hasNext()) {
String name = in.nextName();
BoundField field = boundFields.get(name);
if (field == null || !field.deserialized) {
in.skipValue();
} else {
field.read(in, instance);
}
}
} catch (IllegalStateException e) {
throw new JsonSyntaxException(e);
} catch (IllegalAccessException e) {
throw new AssertionError(e);
}
in.endObject();
return instance;
}
@Override
public void write(JsonWriter out, T value) throws IOException {
if (value == null) {
out.nullValue();
return;
}
out.beginObject();
try {
for (BoundField boundField : boundFields.values()) {
if (boundField.writeField(value)) {
out.name(boundField.name);
boundField.write(out, value);
}
}
} catch (IllegalAccessException e) {
throw new AssertionError(e);
}
out.endObject();
}
}
此处针对server返回的一个转义的object,即objct被“”包裹,其实就是一个字符串,做了特殊处理,即此种情况只要满足预定的object ,也可正常解析,即下面的“data” 定义成String可正常解析,data定义成实体类也可正常解析
{
"id": "",
"name":"sssss",
"url": "",
"title": "培养一种习惯",
"data": "{\"url\":\"https://www.baidu.com/event/emlesson\",\"intentData\":{\"className_ios\":\"EkwWebViewBaseVC\",\"className_android\":\"com.fangyeren.serialization.MainActivity\"}}"
}
6、ARRAY 类型适配器,将Gson中的CollectionTypeAdapterFactory 复制出来,修改适配器代码,这里同上,array 被转义的情况,也可正常解析
private static final class Adapter<E> extends TypeAdapter<Collection<E>> {
private final TypeAdapter<E> elementTypeAdapter;
private final ObjectConstructor<? extends Collection<E>> constructor;
public Adapter(Gson context, Type elementType,
TypeAdapter<E> elementTypeAdapter,
ObjectConstructor<? extends Collection<E>> constructor) {
this.elementTypeAdapter = new TypeAdapterRuntimeTypeWrapper<E>(context, elementTypeAdapter, elementType);
this.constructor = constructor;
}
@Override
public Collection<E> read(JsonReader in) throws IOException {
//增加判断是错误NULL的类型(应该是ARRAY),移动in的下标到结束,移动下标的代码在下方
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return constructor.construct();
}
//增加判断是错误OBJECT的类型(应该是ARRAY),移动in的下标到结束,移动下标的代码在下方
if (in.peek() == JsonToken.BEGIN_OBJECT) {
GsonUtils.readObject(in);
return constructor.construct();
}
//增加判断是错误的NUMBER的类型(应该是ARRAY),移动in的下标到结束,移动下标的代码在下方
if (in.peek() == JsonToken.NUMBER) {
in.nextDouble();
return constructor.construct();
}
//增加判断是错误的String的类型(应该是ARRAY),移动in的下标到结束,移动下标的代码在下方
//如果给的ARRAY是一个转义的字符串,此处会单独处理解析返回
if (in.peek() == JsonToken.STRING) {
String value = in.nextString();
LogTagsUtils.i("===collection====value:" + value);
if(value.startsWith("[") && value.endsWith("]")){
return CommonJsonBuilder.fromJson(value, constructor.construct().getClass());
}
return constructor.construct();
}
//增加判断是错误的name的类型(应该是object),移动in的下标到结束,移动下标的代码在下方
if (in.peek() == JsonToken.NAME) {
in.nextName();
return constructor.construct();
}
//增加判断是错误的boolean的类型(应该是object),移动in的下标到结束,移动下标的代码在下方
if (in.peek() == JsonToken.BOOLEAN) {
in.nextBoolean();
return constructor.construct();
}
Collection<E> collection = constructor.construct();
in.beginArray();
while (in.hasNext()) {
E instance = elementTypeAdapter.read(in);
collection.add(instance);
}
in.endArray();
return collection;
}
@Override
public void write(JsonWriter out, Collection<E> collection) throws IOException {
if (collection == null) {
out.nullValue();
return;
}
out.beginArray();
for (E element : collection) {
elementTypeAdapter.write(out, element);
}
out.endArray();
}
}
7、Map 类型适配器,将Gson中的MapTypeAdapterFactory 复制出来,修改适配器代码,这里同上,Map 被转义的情况,也可正常解析
private final class Adapter<K, V> extends TypeAdapter<Map<K, V>> {
private final TypeAdapter<K> keyTypeAdapter;
private final TypeAdapter<V> valueTypeAdapter;
private final ObjectConstructor<? extends Map<K, V>> constructor;
public Adapter(Gson context, Type keyType, TypeAdapter<K> keyTypeAdapter,
Type valueType, TypeAdapter<V> valueTypeAdapter,
ObjectConstructor<? extends Map<K, V>> constructor) {
this.keyTypeAdapter =
new TypeAdapterRuntimeTypeWrapper<K>(context, keyTypeAdapter, keyType);
this.valueTypeAdapter =
new TypeAdapterRuntimeTypeWrapper<V>(context, valueTypeAdapter, valueType);
this.constructor = constructor;
}
@Override public Map<K, V> read(JsonReader in) throws IOException {
JsonToken peek = in.peek();
//增加判断是错误NULL的类型(应该是OBJECT),移动in的下标到结束,移动下标的代码在下方
if (peek == JsonToken.NULL) {
in.nextNull();
return constructor.construct();
}
//增加判断是错误NUMBER的类型(应该是OBJECT),移动in的下标到结束,移动下标的代码在下方
if (in.peek() == JsonToken.NUMBER) {
in.nextDouble();
return constructor.construct();
}
//增加判断是错误STRING的类型(应该是OBJECT),移动in的下标到结束,移动下标的代码在下方
if(peek == JsonToken.STRING){
String value = in.nextString();
LogTagsUtils.i("===map====value:" + value);
if(value.startsWith("{")&&value.endsWith("}")){
return CommonJsonBuilder.fromJson(value,new TypeToken<Map<K, V>>() { }.getType());
}
return constructor.construct();
}
//增加判断是错误NAME的类型(应该是OBJECT),移动in的下标到结束,移动下标的代码在下方
if (in.peek() == JsonToken.NAME) {
in.nextName();
return constructor.construct();
}
//增加判断是错误BOOLEAN的类型(应该是OBJECT),移动in的下标到结束,移动下标的代码在下方
if (in.peek() == JsonToken.BOOLEAN) {
in.nextBoolean();
return constructor.construct();
}
//增加判断是错误BEGIN_ARRAY的类型(应该是OBJECT),移动in的下标到结束,移动下标的代码在下方
if (in.peek() == JsonToken.BEGIN_ARRAY) {
GsonUtils.readArray(in);
LogTagsUtils.i("==7=in.peek:" + peek);
return constructor.construct();
}
Map<K, V> map = constructor.construct();
if (peek == JsonToken.BEGIN_ARRAY) {
in.beginArray();
while (in.hasNext()) {
in.beginArray(); // entry array
K key = keyTypeAdapter.read(in);
V value = valueTypeAdapter.read(in);
V replaced = map.put(key, value);
if (replaced != null) {
throw new JsonSyntaxException("duplicate key: " + key);
}
in.endArray();
}
in.endArray();
} else {
in.beginObject();
while (in.hasNext()) {
JsonReaderInternalAccess.INSTANCE.promoteNameToValue(in);
K key = keyTypeAdapter.read(in);
V value = valueTypeAdapter.read(in);
V replaced = map.put(key, value);
if (replaced != null) {
throw new JsonSyntaxException("duplicate key: " + key);
}
}
in.endObject();
}
return map;
}
四、结语
好了,到这里已经结束了,基本的思路就是通过反射获取到ConstructorConstructor 中instanceCreators 实例,然后注册自定义的适配器,数字类型适配器(byte/short/int/long/float/double)、Boolean类型适配器、String 类型适配、Map类型适配器、ARRAY类型适配器、OBJECT类型适配器,在自定义的适配器中处理反系列化的代码,兼容自己想处理的错误情况(不包含char类型,原因是json里面的数据格式必须为字符串或者数字类型)
如果有大家有什么问题可以给我留言,或者到github上提交issues ,好久没有写博客了,如果有不到位的地方,欢迎指正,一同进步,感谢阅读 ~