Retrofit之Gson解析原理浅析


本文接着上一片博客 Retrofit网络请求过程原理分析的结尾 ReponseBodyConverter原理继续分析,场景是:当一个网络请求返回时,Gson是怎么对输入流进行解析的。我们知道当OkHttpCall返回数据时会调用parseResponse()方法来解析返回的数据。这里假设调用GsonResponseBodyConverter类来实现数据解析(即在初始化Retrofit时传入GsonConverterFactory添加到转化器工厂列表中)。下面看一下GsonResponseBodyConverter的convert()方法是如何解析的:

//GsonResponseBodyConverter.java
@Override
public T convert(ResponseBody value) throws IOException {
  JsonReader jsonReader = gson.newJsonReader(value.charStream());
  try {
    T result = adapter.read(jsonReader);
    if (jsonReader.peek() != JsonToken.END_DOCUMENT) {
      throw new JsonIOException("JSON document was not fully consumed.");
    }
    return result;
  } finally {
    value.close();
  }
}

这个函数逻辑十分清晰,采用适配器模式来设计代码,设及到的类分别为JsonReader、TypeAdapter和Gson,下面通过一张简图来阐述他们各自的功能以及相互间关系:
在这里插入图片描述

  1. JsonReader将服务端返回的Json数据以流的形式读入,保存在类型为Reader的本地变量in中;
  2. TypeAdapter将Json数据流解析成结构化对象T,其内部的fromJson()方法即是完成这一工作;TypeAdapter是一个虚拟类,定义了转换的顶层接口,具体功能是在其子类中实现的;
  3. Gson是解析的主要类,内部采用工厂设计模式来实现不同TypeAdapter的创建,其成员变量fatories保存了TypeAdapterFactory列表,成员函数getAdapter(type)则根据不同的type去匹配factories中的一个工厂类,然后调用该工厂类的create()方法得到一个相应的TypeAdapter对象。

1、TypeAdapter的产生过程

采用工厂设计模式产生TypeAdapter,不同的工厂类是在Gson的构造函数中添加的:

//Gson.java
Gson(final Excluder excluder, final FieldNamingStrategy fieldNamingStrategy,
      final Map<Type, InstanceCreator<?>> instanceCreators, boolean serializeNulls,
      boolean complexMapKeySerialization, boolean generateNonExecutableGson, boolean htmlSafe,
      boolean prettyPrinting, boolean lenient, boolean serializeSpecialFloatingPointValues,
      LongSerializationPolicy longSerializationPolicy, String datePattern, int dateStyle,
      int timeStyle, List<TypeAdapterFactory> builderFactories,
      List<TypeAdapterFactory> builderHierarchyFactories,
      List<TypeAdapterFactory> factoriesToBeAdded) {

    List<TypeAdapterFactory> factories = new ArrayList<TypeAdapterFactory>();

    // built-in type adapters that cannot be overridden
    factories.add(TypeAdapters.JSON_ELEMENT_FACTORY);
    factories.add(ObjectTypeAdapter.FACTORY);

    // the excluder must precede all adapters that handle user-defined types
    factories.add(excluder);

    // users' type adapters
    factories.addAll(factoriesToBeAdded);

    // type adapters for basic platform types
    factories.add(TypeAdapters.STRING_FACTORY);
    factories.add(TypeAdapters.INTEGER_FACTORY);
    factories.add(TypeAdapters.BOOLEAN_FACTORY);
    factories.add(TypeAdapters.BYTE_FACTORY);
    factories.add(TypeAdapters.SHORT_FACTORY);
    TypeAdapter<Number> longAdapter = longAdapter(longSerializationPolicy);
    factories.add(TypeAdapters.newFactory(long.class, Long.class, longAdapter));
    factories.add(TypeAdapters.newFactory(double.class, Double.class,
            doubleAdapter(serializeSpecialFloatingPointValues)));
    factories.add(TypeAdapters.newFactory(float.class, Float.class,
            floatAdapter(serializeSpecialFloatingPointValues)));
    factories.add(TypeAdapters.NUMBER_FACTORY);
    factories.add(TypeAdapters.ATOMIC_INTEGER_FACTORY);
    factories.add(TypeAdapters.ATOMIC_BOOLEAN_FACTORY);
    factories.add(TypeAdapters.newFactory(AtomicLong.class, atomicLongAdapter(longAdapter)));
    factories.add(TypeAdapters.newFactory(AtomicLongArray.class, atomicLongArrayAdapter(longAdapter)));
    factories.add(TypeAdapters.ATOMIC_INTEGER_ARRAY_FACTORY);
    factories.add(TypeAdapters.CHARACTER_FACTORY);
    factories.add(TypeAdapters.STRING_BUILDER_FACTORY);
    factories.add(TypeAdapters.STRING_BUFFER_FACTORY);
    factories.add(TypeAdapters.newFactory(BigDecimal.class, TypeAdapters.BIG_DECIMAL));
    factories.add(TypeAdapters.newFactory(BigInteger.class, TypeAdapters.BIG_INTEGER));
    factories.add(TypeAdapters.URL_FACTORY);
    factories.add(TypeAdapters.URI_FACTORY);
    factories.add(TypeAdapters.UUID_FACTORY);
    factories.add(TypeAdapters.CURRENCY_FACTORY);
    factories.add(TypeAdapters.LOCALE_FACTORY);
    factories.add(TypeAdapters.INET_ADDRESS_FACTORY);
    factories.add(TypeAdapters.BIT_SET_FACTORY);
    factories.add(DateTypeAdapter.FACTORY);
    factories.add(TypeAdapters.CALENDAR_FACTORY);
    factories.add(TimeTypeAdapter.FACTORY);
    factories.add(SqlDateTypeAdapter.FACTORY);
    factories.add(TypeAdapters.TIMESTAMP_FACTORY);
    factories.add(ArrayTypeAdapter.FACTORY);
    factories.add(TypeAdapters.CLASS_FACTORY);

    // type adapters for composite and user-defined types
    factories.add(new CollectionTypeAdapterFactory(constructorConstructor));
    factories.add(new MapTypeAdapterFactory(constructorConstructor, complexMapKeySerialization));
    this.jsonAdapterFactory = new JsonAdapterAnnotationTypeAdapterFactory(constructorConstructor);
    factories.add(jsonAdapterFactory);
    factories.add(TypeAdapters.ENUM_FACTORY);
    factories.add(new ReflectiveTypeAdapterFactory(
        constructorConstructor, fieldNamingStrategy, excluder, jsonAdapterFactory));

    this.factories = Collections.unmodifiableList(factories);
  }

可以看到在factories成员变量中添加了许多工厂类,这些工厂类的定义在TypeAdapters.java类中,这里特别提一下ReflectiveTypeAdapterFactory工厂类,它是最后添加的,就是说只有前面添加的工厂类都没有匹配成功的情况下,才会用反射的形式来将流数据解析成结构化对象。下面看一下getAdapter()方法是怎么匹配工厂类的:

//Gson.java
public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
    //1.先从缓存中获取该type对应的TypeAdapter
    TypeAdapter<?> cached = typeTokenCache.get(type == null ? NULL_KEY_SURROGATE : type);
    if (cached != null) {
      return (TypeAdapter<T>) cached;
    }

    Map<TypeToken<?>, FutureTypeAdapter<?>> threadCalls = calls.get();
    boolean requiresThreadLocalCleanup = false;
    if (threadCalls == null) {
      threadCalls = new HashMap<TypeToken<?>, FutureTypeAdapter<?>>();
      calls.set(threadCalls);
      requiresThreadLocalCleanup = true;
    }

    //2、从ThreadLocal中获取同一个请求的TypeAdapter
    // the key and value type parameters always agree
    FutureTypeAdapter<T> ongoingCall = (FutureTypeAdapter<T>) threadCalls.get(type);
    if (ongoingCall != null) {
      return ongoingCall;
    }

    //3、从注册的factories中匹配type对应的factory,并creat相应的TypeAdapter,
    //且缓存在threadCalls和typeTokenCache中。
    try {
      FutureTypeAdapter<T> call = new FutureTypeAdapter<T>();
      threadCalls.put(type, call);

      for (TypeAdapterFactory factory : factories) {
        TypeAdapter<T> candidate = factory.create(this, type);
        if (candidate != null) {
          call.setDelegate(candidate);
          typeTokenCache.put(type, candidate);
          return candidate;
        }
      }
      throw new IllegalArgumentException("GSON (" + GsonBuildConfig.VERSION + ") cannot handle " + type);
    } finally {
      threadCalls.remove(type);

      if (requiresThreadLocalCleanup) {
        calls.remove();
      }
    }
  }

注释已经很清楚的解释了这一流程,大致是先从typeTokenCache中获取,然后再从threadCalls线程局部变量中获取,最后才是匹配工厂生产相应的TypeAdapter并缓存。下面看一下ReflectiveTypeAdapterFactory类创建ReflectiveTypeAdapter的过程:

//ReflectiveTypeAdapterFactory.java
@Override public <T> TypeAdapter<T> create(Gson gson, final TypeToken<T> type) {
  Class<? super T> raw = type.getRawType();

  if (!Object.class.isAssignableFrom(raw)) {
    return null; // it's a primitive!
  }

  ObjectConstructor<T> constructor = constructorConstructor.get(type);
  return new Adapter<T>(constructor, getBoundFields(gson, type, raw));
}

1.1 构造器实例化过程

在创建Adapter前,首先会创建一个ObjectConstructor对象和一个String-BoundField的Map,然后又做为成员对象保存在Adapter中。创建ObjectConstructor对象是依靠ConstructorConstructor类来实现的,也是工厂模式,ConstructorConstructor相当于产生ObjectConstructor的工厂类,其get(TypeToken typeToken)方法用于根据typeToken获取对应类型的构造器:

public <T> ObjectConstructor<T> get(TypeToken<T> typeToken) {
    final Type type = typeToken.getType();
    final Class<? super T> rawType = typeToken.getRawType();

    // first try an instance creator

    @SuppressWarnings("unchecked") // types must agree
    final InstanceCreator<T> typeCreator = (InstanceCreator<T>) instanceCreators.get(type);
    if (typeCreator != null) {
      return new ObjectConstructor<T>() {
        @Override public T construct() {
          return typeCreator.createInstance(type);
        }
      };
    }

    // Next try raw type match for instance creators
    @SuppressWarnings("unchecked") // types must agree
    final InstanceCreator<T> rawTypeCreator =
        (InstanceCreator<T>) instanceCreators.get(rawType);
    if (rawTypeCreator != null) {
      return new ObjectConstructor<T>() {
        @Override public T construct() {
          return rawTypeCreator.createInstance(type);
        }
      };
    }

	//1.通过反射无参构造函数来生成对象
    ObjectConstructor<T> defaultConstructor = newDefaultConstructor(rawType);
    if (defaultConstructor != null) {
      return defaultConstructor;
    }

	//2.通过反射为 Collection 和 Map 等集合框架类型来生成对象
    ObjectConstructor<T> defaultImplementation = newDefaultImplementationConstructor(type, rawType);
    if (defaultImplementation != null) {
      return defaultImplementation;
    }

    // finally try unsafe
    //3.通过 Unsafe 包来生成对象,是最后兜底的方案
    return newUnsafeAllocator(type, rawType);
  }

看一下其中默认无参Constructor的产生方式:

//ConstructorConstructor.java
private <T> ObjectConstructor<T> newDefaultConstructor(Class<? super T> rawType) {
    try {
      final Constructor<? super T> constructor = rawType.getDeclaredConstructor();
      if (!constructor.isAccessible()) {
        accessor.makeAccessible(constructor);
      }
      return new ObjectConstructor<T>() {
        @SuppressWarnings("unchecked") // T is the same raw type as is requested
        @Override public T construct() {
          try {
            Object[] args = null;
            return (T) constructor.newInstance(args);
          } catch (InstantiationException e) {
            // TODO: JsonParseException ?
            throw new RuntimeException("Failed to invoke " + constructor + " with no args", e);
          } catch (InvocationTargetException e) {
            // TODO: don't wrap if cause is unchecked!
            // TODO: JsonParseException ?
            throw new RuntimeException("Failed to invoke " + constructor + " with no args",
                e.getTargetException());
          } catch (IllegalAccessException e) {
            throw new AssertionError(e);
          }
        }
      };
    } catch (NoSuchMethodException e) {
      return null;
    }
  }

这里创建了一个类型为ObjectConstructor的匿名对象,constructor对应rawType的零参数构造器,然后调用该构造器初始化一个零参数实例,参数args = null。

1.2 反序列化name列表获取过程

反序列化name列表获取过程是在getBoundFields()函数中实现的:

//ReflectiveTypeAdapterFactory.java
private Map<String, BoundField> getBoundFields(Gson context, TypeToken<?> type, Class<?> raw) {
    Map<String, BoundField> result = new LinkedHashMap<String, BoundField>();
    if (raw.isInterface()) {
      return result;
    }

    Type declaredType = type.getType();
    while (raw != Object.class) {
      //获取raw所有声明的字段
      Field[] fields = raw.getDeclaredFields();
      for (Field field : fields) {
      	//这里可以控制那些字段需要在序列化/反序列化过程中跳过
        boolean serialize = excludeField(field, true);
        boolean deserialize = excludeField(field, false);
        if (!serialize && !deserialize) {
          continue;
        }
        accessor.makeAccessible(field);
        Type fieldType = $Gson$Types.resolve(type.getType(), raw, field.getGenericType());
        //这里可以根据命名策略来获取字段的名字
        List<String> fieldNames = getFieldNames(field);
        BoundField previous = null;
        for (int i = 0, size = fieldNames.size(); i < size; ++i) {
          String name = fieldNames.get(i);
          if (i != 0) serialize = false; // only serialize the default name
          BoundField boundField = createBoundField(context, field, name,
              TypeToken.get(fieldType), serialize, deserialize);
          BoundField replaced = result.put(name, boundField);
          if (previous == null) previous = replaced;
        }
        if (previous != null) {
          throw new IllegalArgumentException(declaredType
              + " declares multiple JSON fields named " + previous.name);
        }
      }
      type = TypeToken.get($Gson$Types.resolve(type.getType(), raw, raw.getGenericSuperclass()));
      raw = type.getRawType();
    }
    return result;
  }

这里的主要逻辑是在循环中,其中While循环是保证获取到raw及其父类所有的字段,第一个for循环是遍历raw的所有字段,每一个字段可能对应多个注解,所以第二个for循环是遍历每个字段的多个注解,是在getFieldNames()中实现的:

//ReflectiveTypeAdapterFactory.java
private List<String> getFieldNames(Field f) {
	//先获取f的SerializedName注解
    SerializedName annotation = f.getAnnotation(SerializedName.class);
    if (annotation == null) {
      //如果没有SerializedName注解才会用fieldNamingPolicy来转换名字
      String name = fieldNamingPolicy.translateName(f);
      return Collections.singletonList(name);
    }

    String serializedName = annotation.value();
    String[] alternates = annotation.alternate();
    if (alternates.length == 0) {
      return Collections.singletonList(serializedName);
    }

    List<String> fieldNames = new ArrayList<String>(alternates.length + 1);
    fieldNames.add(serializedName);
    for (String alternate : alternates) {
      fieldNames.add(alternate);
    }
    return fieldNames;
  }

这里的变量fieldNamingPolicy的类型是FieldNamingStrategy,其实现类是FieldNamingPolicy枚举类,枚举对象有IDENTITY、UPPER_CAMEL_CASE、UPPER_CAMEL_CASE_WITH_SPACES、LOWER_CASE_WITH_UNDERSCORES、LOWER_CASE_WITH_DASHES、 LOWER_CASE_WITH_DOTS。

2. 数据读取(反序列化)过程

ReflectiveTypeAdapterFactory生产的Adapter对象用于将二进制数据列反序列化为类型化对象,在Adapter的read()方法中来实现的:

@Override 
public T read(JsonReader in) throws IOException {
  if (in.peek() == JsonToken.NULL) {
    in.nextNull();
    return null;
  }
  //先用该类型的零参构造器来实例化该类型的实例
  T instance = constructor.construct();

  try {
    in.beginObject();
    while (in.hasNext()) {
      //先读出name
      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;
}

在While循环中先从输入流in中读出name字段,然后再将name为key从boundFields获取该name对应的field,最后再从输入流in中读出该file的值。读出name的过程为:

public String nextName() throws IOException {
    int p = peeked;
    if (p == PEEKED_NONE) {
      p = doPeek();
    }
    String result;
    if (p == PEEKED_UNQUOTED_NAME) {
      result = nextUnquotedValue();
    } else if (p == PEEKED_SINGLE_QUOTED_NAME) {
      result = nextQuotedValue('\'');
    } else if (p == PEEKED_DOUBLE_QUOTED_NAME) {
      result = nextQuotedValue('"');
    } else {
      throw new IllegalStateException("Expected a name but was " + peek() + locationString());
    }
    peeked = PEEKED_NONE;
    pathNames[stackSize - 1] = result;
    return result;
  }

这段代码逻辑很清晰,即先判断读出的开头p是否是没有引号的name,再判断p是否是单引号引用的name,最后判断p是否是双引号引用的name。然后分别读出其后面的name。接下来是调用BoundField的read()方法从输入流中读出name对应的BoundField值,BoundField对象是在createBoundField()方法中创建的:

//ReflectiveTypeAdapterFactory.java
private ReflectiveTypeAdapterFactory.BoundField createBoundField(
      final Gson context, final Field field, final String name,
      final TypeToken<?> fieldType, boolean serialize, boolean deserialize) {
    final boolean isPrimitive = Primitives.isPrimitive(fieldType.getRawType());
    
    // special casing primitives here saves ~5% on Android...
    //1. 获取TypeAdapter
    JsonAdapter annotation = field.getAnnotation(JsonAdapter.class);
    TypeAdapter<?> mapped = null;
    //1.1. 如果file有@JsonAdapter注解,则获取注解的TypeAdapter
    if (annotation != null) {
      mapped = jsonAdapterFactory.getTypeAdapter(
          constructorConstructor, context, fieldType, annotation);
    }
    final boolean jsonAdapterPresent = mapped != null;
    //1.2. 如果没有@JsonAdapter注解, 则获取Gson中默认注册的fieldType对应的TypeAdapter
    if (mapped == null) mapped = context.getAdapter(fieldType);

	//2. 实例化BoundField对象并返回
    final TypeAdapter<?> typeAdapter = mapped;
    return new ReflectiveTypeAdapterFactory.BoundField(name, serialize, deserialize) {
    
      @SuppressWarnings({"unchecked", "rawtypes"}) // the type adapter and field type always agree
      @Override 
      void write(JsonWriter writer, Object value)throws IOException, IllegalAccessException {
        Object fieldValue = field.get(value);
        TypeAdapter t = jsonAdapterPresent ? typeAdapter
            : new TypeAdapterRuntimeTypeWrapper(context, typeAdapter, fieldType.getType());
        t.write(writer, fieldValue);
      }
      
      @Override 
      void read(JsonReader reader, Object value)throws IOException, IllegalAccessException {
        Object fieldValue = typeAdapter.read(reader);
        if (fieldValue != null || !isPrimitive) {
          field.set(value, fieldValue);
        }
      }
      
      @Override 
      public boolean writeField(Object value) throws IOException, IllegalAccessException {
        if (!serialized) return false;
        Object fieldValue = field.get(value);
        return fieldValue != value; // avoid recursion for example for Throwable.cause
      }
    };
  }

先通过field的JsonAdapter注解获取,然后通过Gson默认组册的filed对应的TypeAdapter。后一种获取方式文章开通有论述,看一下前一种TypeAdapter的获取方式:

//ReflectiveTypeAdapterFactory.java
TypeAdapter<?> getTypeAdapter(ConstructorConstructor constructorConstructor, Gson gson,
      TypeToken<?> type, JsonAdapter annotation) {
    Object instance = constructorConstructor.get(TypeToken.get(annotation.value())).construct();

    TypeAdapter<?> typeAdapter;
    if (instance instanceof TypeAdapter) {
      typeAdapter = (TypeAdapter<?>) instance;
    } else if (instance instanceof TypeAdapterFactory) {
      typeAdapter = ((TypeAdapterFactory) instance).create(gson, type);
    } else if (instance instanceof JsonSerializer || instance instanceof JsonDeserializer) {
      JsonSerializer<?> serializer = instance instanceof JsonSerializer
          ? (JsonSerializer) instance
          : null;
      JsonDeserializer<?> deserializer = instance instanceof JsonDeserializer
          ? (JsonDeserializer) instance
          : null;
      typeAdapter = new TreeTypeAdapter(serializer, deserializer, gson, type, null);
    } else {}

    if (typeAdapter != null && annotation.nullSafe()) {
      typeAdapter = typeAdapter.nullSafe();
    }

    return typeAdapter;
  }

这里创建了一个BoundField匿名对象并返回,其read()方法中也是调用typeAdapter的read方法,注意此时还在ReflectiveTypeAdapterFactory中,这里的typeAdapter是调用Gson对象的getAdapter(fieldType)方法获取的,假设fieldType类型是Boolean,Boolean类型对应的TypeAdapter是在TypeAdapters类中定义的:

public static final TypeAdapter<Boolean> BOOLEAN = new TypeAdapter<Boolean>() {
    @Override
    public Boolean read(JsonReader in) throws IOException {
      JsonToken peek = in.peek();
      if (peek == JsonToken.NULL) {
        in.nextNull();
        return null;
      } else if (peek == JsonToken.STRING) {
        // support strings for compatibility with GSON 1.7
        return Boolean.parseBoolean(in.nextString());
      }
      return in.nextBoolean();
    }
    @Override
    public void write(JsonWriter out, Boolean value) throws IOException {
      out.value(value);
    }
  };

这里的BOOLEAN匿名对象是在1、TypeAdapter的产生过程中添加到Gson中的factories中的。可以看到是调用JsonReader的nextBoolean()方法来读取Boolean值的:

public boolean nextBoolean() throws IOException {
    int p = peeked;
    if (p == PEEKED_NONE) {
      p = doPeek();
    }
    if (p == PEEKED_TRUE) {
      peeked = PEEKED_NONE;
      pathIndices[stackSize - 1]++;
      return true;
    } else if (p == PEEKED_FALSE) {
      peeked = PEEKED_NONE;
      pathIndices[stackSize - 1]++;
      return false;
    }
    throw new IllegalStateException("Expected a boolean but was " + peek() + locationString());
  }

3. 实战

背景
Gson解析String类型时,若服务端返回"null",则会通过反射反序列化一个空对象,且会绕过Kotlin的非空检查,是对Kotlin的不兼容,参考文章Gson 和 Kotlin data class 的避坑指南
思路
根据2. 数据读取(反序列化)过程的分析可知:Gson在反序列化的过程中是通过name找到对应的BoundField,然后通过BoundField中TypeAdapter来根据name的类型来解析name的值的。比如对于java字符串"{“name”:null}"对应解析成class UserBean(val userAge: Int),则name是userAge,name的类型是Int,name的值则是null。在ReflectiveTypeAdapterFactory类的createBoundField()方法中获取TypeAdapter有两种形式:1.通过field的JsonAdapter注解获取,2.通过Gson默认注册的filed对应的TypeAdapter。第二种方式可以参考前文1、TypeAdapter的产生过程一节的论述,第一种方式可以参看上一节的ReflectiveTypeAdapterFactory.getTypeAdapter()的代码,其内部也是通过ConstructorConstructor.get(TypeToken typeToken)来构造TypeAdapter/TypeAdapterFactory实例的。对于String类型,是采用Gson默认注册的类型为TypeAdapterFactory的STRING_FACTORY实例来反序列化的,因此将其替换掉,注册一个自定义的TypeAdapterFactory即可。
实现1:
通过反射来实现替换:

fun replaceStringFactories(gson: Gson) {
    try {
        val startTime = System.currentTimeMillis()
        gson.javaClass.getDeclaredField("factories").apply {
            isAccessible = true
            val factories = get(gson)
            getDeclareFiledRecursive(factories.javaClass, "list", 5).apply {
                isAccessible = true
                val factoriesInner = get(factories)
                Timber.d("factories: ${
                    factoriesInner.javaClass.isAssignableFrom(ArrayList::class.java)
                }")
                if (factoriesInner.javaClass.isAssignableFrom(ArrayList::class.java)) {
                    val stringIndex = (factoriesInner as ArrayList<TypeAdapterFactory>).indexOf(
                            TypeAdapters.STRING_FACTORY)
                    Timber.d("stringIndex, $stringIndex")
                    factoriesInner.remove(TypeAdapters.STRING_FACTORY)
                    val newString = object : TypeAdapter<String?>() {
                        @Throws(IOException::class)
                        override fun read(`in`: JsonReader): String? {
                            val peek = `in`.peek()
                            if (peek == JsonToken.NULL) {
                                `in`.nextNull()
                                return ""
                            }

                            return if (peek == JsonToken.BOOLEAN) {
                                Boolean.toString(`in`.nextBoolean())
                            } else `in`.nextString()
                        }

                        @Throws(IOException::class)
                        override fun write(out: JsonWriter, value: String?) {
                            out.value(value)
                        }
                    }
                    factoriesInner.add(stringIndex, TypeAdapters.newFactory(String::class.java,
                            newString))
                }
            }
        }
        Timber.d("reflection spend ${System.currentTimeMillis() - startTime}")
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

private fun <T> getDeclareFiledRecursive(clazz: Class<T>, field: String, recursiveTime: Int):
        Field {
    var declareField: Field? = null
    for (i in 0..recursiveTime) {
        declareField = try {
            clazz.getDeclaredField(field)
        } catch (e: NoSuchFieldException) {
            getDeclareFiledRecursive(clazz.superclass, field, recursiveTime - 1)
        }
    }
    return declareField!!
}

实现2
可以自定义TypeAdapter,这就需要自定义一个TypeAdapterFactory,并注册到Gson的factories中,获取某个TypeAdapter来解析数据时,是遍历factories并成功获取第一个TypeAdapter就结束循环。

/**
 * Null string type adapter factory
 * 这个factory方便后续扩展,添加Collection null 替换为[]
 * @constructor Create empty Null string type adapter factory
 */
class NullStringTypeAdapterFactory : TypeAdapterFactory {
    override fun <T : Any?> create(gson: Gson, typeToken: TypeToken<T>): TypeAdapter<T>? {
        val rawType = typeToken.rawType
        if (rawType == String::class.java) {
            return StringNullAdapter() as TypeAdapter<T>
        }
        return null
    }
}

/**
 * String type adapter
 * 将为null的String直接更改为""
 * @constructor Create empty String type adapter
 */
class StringNullAdapter : TypeAdapter<String>() {

    //Object转Json数据
    @Throws(IOException::class)
    override fun write(out: JsonWriter, value: String?) {

        if (value == null) {
            out.value("")
            //一定要return,不然报错 https://github.com/google/gson/issues/1713
            return
        }
        out.value(value)
    }
    @Throws(IOException::class)
    override fun read(jsonReader: JsonReader): String {
        //返回下一个令牌的类型,并不使用它
        if (jsonReader.peek() == JsonToken.NULL) {
            //使用流中的下一个令牌
            //nextNull()如果下一个字段不是null或者流关闭,就会报错
            jsonReader.nextNull()
            return ""
        }
        return jsonReader.nextString()
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值