分享一個(gè)Kotlin搭配Gson的坑
今天發(fā)現(xiàn)服務(wù)端返回的一個(gè)javaBean里面有三個(gè)List<T>其實(shí)是可以合并到一個(gè)List<T>的,所以打算合并一下,遂在javaBean中增加一個(gè)field;
改之前
data class Example(
@SerializedName("a_list") val aList : List<String>,
@SerializedName("b_list") val bList : List<String>,
@SerializedName("c_list") val cList : List<String>
)
改之后
data class Example(
@SerializedName("a_list") val aList : List<String>,
@SerializedName("b_list") val bList : List<String>,
@SerializedName("c_list") val cList : List<String>,
val mixList: MutableList<String> = arrayListOf()
)
fun mix(){
//從服務(wù)端獲取
val example = getExampleData()
example.mixList.apply {
addAll(example.aList)
addAll(example.bList)
addAll(example.cList)
}
}
fun getExampleData() : Example{
return Gson().fromJson(getData(),Example::class.java)
}
然后拋出了mixList的NullPointException
解決方案很簡(jiǎn)單,在mix方法中給mixList賦值
通過(guò)閱讀Gson源碼分析一下
構(gòu)造一個(gè)Person類(lèi)試試
data class Person(
val name : String,
val age : Int,
val job : String = "coder"
)
- 首先是
fromJson
public <T> T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException {
---
TypeToken<T> typeToken = (TypeToken<T>) TypeToken.get(typeOfT);
TypeAdapter<T> typeAdapter = getAdapter(typeToken);
T object = typeAdapter.read(reader);
return object;
---
- 可以看到這里通過(guò)
TypeAdapter來(lái)讀取字符串,
通過(guò)斷點(diǎn)來(lái)到ReflectiveTypeAdapterFactory的getBoundFields方法,
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) {
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;
}
- 看一下這個(gè)
raw的來(lái)源
@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));
}
也就是我們傳進(jìn)來(lái)要轉(zhuǎn)換的結(jié)果class,gson通過(guò)默認(rèn)構(gòu)造函數(shù)構(gòu)造了一個(gè)Person對(duì)象,通過(guò)遍歷field,并進(jìn)行一一匹配填充,而沒(méi)有讀取到的初始值為空,所以我們?cè)?code>data class中賦的值沒(méi)有意義了~

構(gòu)造器.jpg

log.jpg
- 看一下Kotlin的構(gòu)造器問(wèn)題

默認(rèn)構(gòu)造.jpg
也就是說(shuō),我們賦的默認(rèn)值失去了意義~
其實(shí)也沒(méi)啥,就是記錄一下