Android 数据解析工具库|兼容服务端错误类型返回

537 阅读14分钟

一、背景

移动端大多情况下与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 ,好久没有写博客了,如果有不到位的地方,欢迎指正,一同进步,感谢阅读 ~