本文接着上一片博客 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,下面通过一张简图来阐述他们各自的功能以及相互间关系:
- JsonReader将服务端返回的Json数据以流的形式读入,保存在类型为Reader的本地变量in中;
- TypeAdapter将Json数据流解析成结构化对象T,其内部的fromJson()方法即是完成这一工作;TypeAdapter是一个虚拟类,定义了转换的顶层接口,具体功能是在其子类中实现的;
- 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()
}
}