- Gson 是 我們經(jīng)常用來(lái)在 Java 對(duì)象和 JSON 數(shù)據(jù)之間進(jìn)行映射的 庫(kù),今天我們就來(lái)分別講一講其使用和源碼分析
使用詳解
1. 基本的解析與生成
- Gson提供了fromJson() 和toJson() 兩個(gè)直接用于解析和生成的方法候齿,前者實(shí)現(xiàn)反序列化,后者實(shí)現(xiàn)了序列化
- 解析基本數(shù)據(jù)類(lèi)型
val gson = Gson()
val i = gson.fromJson("100", Int::class.java) //100
val d = gson.fromJson("99.99", Double::class.java) //99.99
val b = gson.fromJson("true", Boolean::class.java) // true
val s = gson.fromJson("jin", String::class.java) // String
log("i=$i,d=$d,b=$b,s=$s")
- 生成基本數(shù)據(jù)類(lèi)型
val gson = Gson()
val jsonI: String = gson.toJson(100) // 100
val jsonD: String = gson.toJson(99.99) // 100
val jsonB: String = gson.toJson(false) // false
val jsonS: String = gson.toJson("String") //"String"
log("jsonI=$jsonI,jsonD=$jsonD,jsonB=$jsonB,jsonS=$jsonS")
- 解析及生成自定義對(duì)象
//先定義一個(gè)數(shù)據(jù)模型類(lèi),這里需要注意的一點(diǎn)是在方法內(nèi)部定義的類(lèi)gson解析和生成都是null科贬,所以應(yīng)該放到類(lèi)或單獨(dú)的文件中定義
data class UserInfo(var name: String?, var age: Int?, var emailAddress: String? )
//創(chuàng)建自定義對(duì)象
val user = UserInfo(name = "222", age = 18, "xxx@163.com")
log("user=${user}")
//轉(zhuǎn)為json字符串
val gson = Gson()
val userStr = gson.toJson(user)
log("userStr:$userStr")
//從字符串轉(zhuǎn)為自定義對(duì)象
val user2: UserInfo? = gson.fromJson(userStr, UserInfo::class.java)
log("user2=${user2}")
2. 屬性重命名
@SerializedName 注解的使用
- @SerializedName接收兩個(gè)參數(shù)惦蚊,value字符串對(duì)屬性重命名及alternate數(shù)組為屬性提供多個(gè)備選屬性名
- toJson后的字符串中的屬性名會(huì)以value中的值為準(zhǔn)
- 為字段提供備選屬性名汉规,當(dāng)多種情況同時(shí)出時(shí)干旧,以最后一個(gè)出現(xiàn)的值為準(zhǔn)
- 為數(shù)據(jù)模型類(lèi)添加注解
data class UserInfo(
@SerializedName(value = "name", alternate = ["user_name"]) var name: String?,
@SerializedName("age", alternate = ["user_age", "u_age", "Age"]) var age: Int?,
@SerializedName("emailAddress") var emailAddress: String? = null,
)
- 解析與生成json字符串
val user3: UserInfo? =
gson.fromJson("{\"user_age\":18,\"user_name\":\"333\"}", UserInfo::class.java)
log("user3=$user3")
val user4: UserInfo? =
gson.fromJson("{\"u_age\":18,\"user_name\":\"444\"}", UserInfo::class.java)
log("user4=$user4")
val user5: UserInfo? = gson.fromJson(
"{\"Age\":18,\"user_age\":19,\"u_age\":20,\"user_name\":\"555\"}",
UserInfo::class.java
)
log("user5=$user5")
POJO與JSON的字段映射規(guī)則
- GsonBuilder提供了setFieldNamingPolicy和setFieldNamingStrategy 兩個(gè)方法;
- setFieldNamingPolicy方法與FieldNamingPolicy枚舉配合使用斥杜,提供了如下幾種選擇
val gson = GsonBuilder()
// .setFieldNamingPolicy(FieldNamingPolicy.IDENTITY)//emailAddress
// .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_DASHES)//email-address
// .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)//email_address
// .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)//EmailAddress
.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE_WITH_SPACES)//Email Address
.create()
val user = UserInfo(name = "222", age = 18, "xxx@163.com")
log("setFieldNamingPolicy:${gson.toJson(UserInfo3())}")
- setFieldNamingStrategy與Gson提供的FieldNamingStrategy接口配合使用 實(shí)現(xiàn)自己的規(guī)則
//1. 實(shí)現(xiàn)FieldNamingStrategy接口,定義自己的規(guī)則
class FieldStrategy {
/**
* 采用全部大寫(xiě)的形式
*/
class AllUpperCaseStrategy : FieldNamingStrategy {
override fun translateName(f: Field): String {
return f.name.uppercase(Locale.getDefault())
}
}
/**
* 添加前置 和 后置 注解
*/
class GsonKeyValueCaseStrategy : FieldNamingStrategy {
override fun translateName(f: Field): String {
val gkv: GsonKeyValue? = f.getAnnotation(GsonKeyValue::class.java)
return if (gkv != null) {
if (gkv.value.isNotEmpty()) {
gkv.prefix + gkv.value + gkv.suffix
} else {
gkv.prefix + f.name + gkv.suffix
}
} else {
f.name
}
}
}
}
//2.使用
val gson = GsonBuilder()
.setFieldNamingStrategy(FieldStrategy.AllUpperCaseStrategy())
.setFieldNamingStrategy(FieldStrategy.GsonKeyValueCaseStrategy())
.create()
val user = UserInfo(name = "222", age = 18, "xxx@163.com")
log("setFieldNamingStrategy:${gson.toJson(user)}")
- @SerializedName注解擁有最高優(yōu)先級(jí)高蜂,在加有@SerializedName注解的字段上FieldNamingStrategy不生效
使用GsonBuilder
- 上面我們沒(méi)有通過(guò)Gson()構(gòu)造方法來(lái)創(chuàng)建Gson實(shí)例聪黎,而是使用了GsonBuilder,下面介紹一些其方法
val gsonDIY = GsonBuilder()
//序列化null,Gson在默認(rèn)情況下是不動(dòng)導(dǎo)出值null的鍵的
.serializeNulls()
// 設(shè)置日期時(shí)間格式备恤,另有2個(gè)重載方法
// 在序列化和反序化時(shí)均生效
.setDateFormat("yyyy-MM-dd")
// 禁此序列化內(nèi)部類(lèi)
.disableInnerClassSerialization()
//生成不可執(zhí)行的Json, 其實(shí)就是多了 )]}' 這4個(gè)字符
.generateNonExecutableJson()
//禁止轉(zhuǎn)義html標(biāo)簽
.disableHtmlEscaping()
//格式化輸出
.setPrettyPrinting()
.create() //生成配置好的Gson
//使用
val user8 = UserInfo("888", 18)
val user8Str = gsonDIY.toJson(user8)
log("user8 toJson:${user8Str}")
log("fromJson user8Str:${gsonDIY.fromJson(user8Str, UserInfo::class.java)}")
泛型
val gson = Gson()
val jsonArray = gson.toJson(arrayOf(user2, user3, user4, user5))
val userArr = gson.fromJson(jsonArray, Array<UserInfo>::class.java)
log("userArr=${gson.toJson(userArr)}")
val userList: List<UserInfo> = gson.fromJson(jsonArray, List::class.java) as List<UserInfo>
log("userList=$userList")
//Java泛型使用時(shí)要注意泛型擦除,Gson為我們提供了TypeToken來(lái)實(shí)現(xiàn)對(duì)泛型的支持
val userList2: List<UserInfo?>? =
gson.fromJson(jsonArray, object : TypeToken<List<UserInfo?>?>() {}.type)
log("userList2=$userList2")
泛型的封裝
- 但是每次解析泛型都要寫(xiě)TypeToken就很麻煩稿饰,所以我們可以在工具類(lèi)中做一些簡(jiǎn)單的封裝
fun getListType(type: Type): Type {
return TypeToken.getParameterized(MutableList::class.java, type).type
}
fun getSetType(type: Type): Type {
return TypeToken.getParameterized(MutableSet::class.java, type).type
}
fun getMapType(keyType: Type, valueType: Type): Type {
return TypeToken.getParameterized(MutableMap::class.java, keyType, valueType).type
}
fun getArrayType(type: Type): Type {
return TypeToken.getArray(type).type
}
fun getType(rawType: Type, vararg typeArguments: Type): Type {
return TypeToken.getParameterized(rawType, *typeArguments).type
}
- 或者涉及到實(shí)際業(yè)務(wù),比如網(wǎng)絡(luò)數(shù)據(jù)的解析露泊,還可以像下面這樣再進(jìn)一步封裝一下
/**
* 解析data是object的情況
*/
fun <T> fromJson2Object(json: String?, clazz: Class<T>): BaseHttpResponse<T>? {
val type: Type = getType(BaseHttpResponse::class.java, clazz)
return fromJson(json, type)
}
/**
* 解析data是array的情況
*/
fun <T> fromJson2Array(json: String?, clazz: Class<T>): BaseHttpResponse<MutableList<T?>?>? {
// 生成List<T> 中的 List<T>
val listType: Type = getListType(clazz)
// 根據(jù)List<T>生成完整的BaseHttpResponse<List<T>>
val type: Type = getType(BaseHttpResponse::class.java, listType)
return fromJson(json, type)
}
/**
* 解析data是Map的情況
*/
fun <K, T> fromJson2Map(json: String?, clazz1: Class<K>, clazz2: Class<T>): BaseHttpResponse<MutableMap<K?, T?>?>? {
// 生成BaseHttpResponse<Map<K,T>> 中的 Map<K,T>
val mapType: Type = getMapType(clazz1, clazz2)
// 根據(jù)Map<K,T>生成完整的BaseHttpResponse<Map<K,T>>
val type: Type = getType(BaseHttpResponse::class.java, mapType)
return fromJson(json, type)
}
//網(wǎng)絡(luò)數(shù)據(jù)的基類(lèi)
data class BaseHttpResponse<T>(
@SerializedName(value = "code", alternate = ["Status", "status"]) var code: Int? = null,
@SerializedName(value = "message", alternate = ["Msg", "msg"]) var message: String? = null,
@SerializedName(value = "data", alternate = ["Data"]) var data: T? = null
)
//對(duì)BaseHttpResponse<UserInfo3>的解析
val baseHttpResponse1=BaseHttpResponse(111,"aaa",UserInfo3("ljy",18))
val strResponse1:String=GsonUtils.toJson(baseHttpResponse1)
log("fromJsonObject:${GsonUtils.fromJson2Object(strResponse1,UserInfo3::class.java)}")
//對(duì)List<UserInfo3>的解析
val list=mutableListOf(UserInfo3("ljy",18),UserInfo3("qwer",19))
log("fromJson(json,Type):${GsonUtils.fromJson<List<UserInfo3>>(GsonUtils.toJson(list),GsonUtils.getListType(UserInfo3::class.java))}")
//對(duì)BaseHttpResponse<List<UserInfo3>>的解析
val baseHttpResponse2=BaseHttpResponse<List<UserInfo3>>(111,"aaa",list)
val strResponse2:String=GsonUtils.toJson(baseHttpResponse2)
log("fromJsonArray:${GsonUtils.fromJson2Array(strResponse2,UserInfo3::class.java)}")
//對(duì)Map<String,UserInfo3>的解析
val map= mutableMapOf("key1" to UserInfo3("ljy",18),"key2" to UserInfo3("qwer",19))
log("fromJson(json,Type):${GsonUtils.fromJson<Map<String,UserInfo3>>(GsonUtils.toJson(map),GsonUtils.getMapType(String::class.java,UserInfo3::class.java))}")
//對(duì)BaseHttpResponse<Map<String,UserInfo3>>的解析
val baseHttpResponse3=BaseHttpResponse<List<UserInfo3>>(111,"aaa",map)
val strResponse3:String=GsonUtils.toJson(baseHttpResponse3)
log("fromJsonMap:${GsonUtils.fromJson2Map(strResponse3,String::class.java,UserInfo3::class.java)}")
Gson的序列化喉镰、反序列化
Gson的流式反序列化
- 手動(dòng)的方式: 使用stream包下的JsonReader類(lèi)來(lái)手動(dòng)實(shí)現(xiàn)反序列化,和Android中使用pull解析XML是比較類(lèi)似的
val user6 = UserInfo(null, null, null, null)
val reader = JsonReader(StringReader(userStr))
reader.beginObject()
while (reader.hasNext()) {
when (reader.nextName()) {
"name" ->
user6.name = reader.nextString()
"age" ->
user6.age = reader.nextInt()
"emailAddress" ->
user6.emailAddress = reader.nextString()
"temp" ->
user6.temp = reader.nextString()
"date" ->
user6.date = Date(reader.nextString())
}
}
reader.endObject()
log("user6=$user6")
- 自動(dòng)方式最終都是通過(guò)JsonReader來(lái)實(shí)現(xiàn)的惭笑,如果第一個(gè)參數(shù)是String類(lèi)型侣姆,那么Gson會(huì)創(chuàng)建一個(gè)StringReader轉(zhuǎn)換成流操作,源碼如下:
public <T> T fromJson(String json, Type typeOfT) throws JsonSyntaxException {
if (json == null) {
return null;
}
StringReader reader = new StringReader(json);
T target = (T) fromJson(reader, typeOfT);
return target;
}
Gson的流式序列化
- 手動(dòng)
val user7 = UserInfo("777", 17, "7777@qq.com")
// val writer = JsonWriter(OutputStreamWriter(System.out))
val stringWriter = StringWriter()
val writer = JsonWriter(stringWriter)
writer.beginObject()
.name("name").value(user7.name)
.name("age").value(user7.age)
.name("emailAddress").nullValue()
.endObject()
writer.flush()
log("user7=$stringWriter")
- 自動(dòng)
// PrintStream(System.out) 、StringBuilder沉噩、StringBuffer和*Writer都實(shí)現(xiàn)了Appendable接口铺敌。
gson.toJson(user,System.out)
val str1 = gson.toJson(user)
//toJson源碼如下:
//public String toJson(Object src, Type typeOfSrc) {
// StringWriter writer = new StringWriter();
// toJson(src, typeOfSrc, writer);
// return writer.toString();
//}
字段過(guò)濾的幾種方法
1. @Expose注解
- 基于@Expose注解:需要導(dǎo)出的字段上加上@Expose 注解,不導(dǎo)出的字段不加
data class UserInfo(
@Expose //@Expose提供了兩個(gè)屬性屁擅,且默認(rèn)值都為true
var name: String?,
@Expose(deserialize = true,serialize = true) //序列化和反序列化都都生效
var age: Int?,
@Expose(deserialize = true,serialize = false) //反序列化時(shí)生效
var emailAddress: String? = null,
@Expose(deserialize = false,serialize = true) //序列化時(shí)生效
var date: Date? = Date(),
@Expose(deserialize = false,serialize = false) // 和不寫(xiě)注解一樣
var temp: String? = "沒(méi)啥用的temp"
)
- 在使用Gson時(shí)也要用GsonBuilder調(diào)用excludeFieldsWithoutExposeAnnotation方法使其支持@Expose
val gson3 = GsonBuilder()
.excludeFieldsWithoutExposeAnnotation()
.create()
gson3.toJson(user8)
log("user8 toJson:${gson3.toJson(user8)}")
2. 基于版本
- Gson在對(duì)基于版本的字段導(dǎo)出提供了兩個(gè)注解 @Since 和 @Until,都接收一個(gè)Double值
data class UserInfo2(
var name: String?,
@Since(3.0)
var age: Int?,
@Until(6.0)
var emailAddress: String? = null,
)
- 配合GsonBuilder.setVersion(Double)使用,當(dāng)前版本(GsonBuilder中設(shè)置的版本) 大于等于Since的值時(shí)該字段導(dǎo)出,小于Until的值時(shí)該該字段導(dǎo)出
val user9 = UserInfo2("999", 19, "9999@qq.com")
log("user9 version 1.0:" + GsonBuilder().setVersion(1.0).create().toJson(user9))
log("user9 version 4.0:" + GsonBuilder().setVersion(4.0).create().toJson(user9))
log("user9 version 9.0:" + GsonBuilder().setVersion(9.0).create().toJson(user9))
val user9Str = "{\"age\":19,\"emailAddress\":\"9999@qq.com\",\"name\":\"999\"}"
log("user9Str version 1.0:" + GsonBuilder().setVersion(1.0).create().fromJson(user9Str, UserInfo2::class.java))
log("user9Str version 4.0:" + GsonBuilder().setVersion(4.0).create().fromJson(user9Str, UserInfo2::class.java))
log("user9Str version 9.0:" + GsonBuilder().setVersion(9.0).create().fromJson(user9Str, UserInfo2::class.java))
3. 基于訪(fǎng)問(wèn)修飾符
- 基于public产弹、static 派歌、final弯囊、private、protected這些訪(fǎng)問(wèn)修飾符胶果,通過(guò)GsonBuilder().excludeFieldsWithModifiers()方法進(jìn)行控制
//用不同的修飾符修飾模型類(lèi)Test的字段
public class Test {
final String finalField = "final";
static String staticField = "static";
public String publicField = "public";
protected String protectedField = "protected";
String defaultField = "default";
boolean man=true;
private String privateField = "private";
}
//排除final,static,private修飾的字段
val gson4 = GsonBuilder()
.excludeFieldsWithModifiers(Modifier.FINAL, Modifier.STATIC, Modifier.PRIVATE)
.create()
log(gson4.toJson(Test()))
4. 基于策略(自定義規(guī)則)
- GsonBuilder的addSerializationExclusionStrategy , addDeserializationExclusionStrategy 兩個(gè)方法分別針對(duì)序列化和反序化
- 兩個(gè)方法入?yún)魅隕xclusionStrategy接口的實(shí)現(xiàn)類(lèi)匾嘱,在其中實(shí)現(xiàn)自己的規(guī)則
val gson5 = GsonBuilder()
.addSerializationExclusionStrategy(object : ExclusionStrategy {
override fun shouldSkipField(f: FieldAttributes): Boolean {
// 這里作判斷,決定要不要排除該字段,return true為排除
if ("emailAddress" == f.name) return true //按字段名排除
val expose = f.getAnnotation(Expose::class.java)
return expose != null && !expose.deserialize //按注解排除:
}
override fun shouldSkipClass(clazz: Class<*>): Boolean {
// 直接排除某個(gè)類(lèi) 早抠,return true為排除,例如排除Boolean.kt和Boolean.java
return clazz == Boolean::class || clazz == Boolean::class.java
}
})
.create()
log("UserInfo3:${gson5.toJson(UserInfo3())}")
log("Test:${gson5.toJson(Test())}")
TypeAdapter
- 用于接管某種類(lèi)型的序列化和反序列化過(guò)程霎烙,包含兩個(gè)注要方法 write(JsonWriter,T) 和 read(JsonReader),其它的方法都是final方法并最終調(diào)用這兩個(gè)抽象方法。
- 自定義UserInfoTypeAdapter
class UserInfoTypeAdapter : TypeAdapter<UserInfo3?>() {
@Throws(IOException::class)
override fun write(out: JsonWriter?, value: UserInfo3?) {
out?.run {
value?.let {
beginObject()
name("name").value(it.name)
name("age").value(it.age)
name("emailAddress").value(it.emailAddress)
endObject()
}
}
}
@Throws(IOException::class)
override fun read(`in`: JsonReader): UserInfo3 {
val user = UserInfo3()
`in`.beginObject()
while (`in`.hasNext()) {
when (`in`.nextName()) {
"name" -> user.name = `in`.nextString()
"age" -> user.age = `in`.nextInt()
"email", "email_address", "emailAddress" -> user.emailAddress =
`in`.nextString()
}
}
`in`.endObject()
return user
}
}
- 為UserInfo3注冊(cè)UserInfoTypeAdapter
val gson8 = GsonBuilder()
.registerTypeAdapter(UserInfo3::class.java, UserInfoTypeAdapter())
.create()
log(gson8.toJson(UserInfo3()))
log(gson8.fromJson("{\"name\":\"ljy\",\"age\":20,\"email_address\":\"xx@qq.com\",\"email\":\"qqq@qq.com\"}", UserInfo3::class.java))
JsonSerializer與JsonDeserializer
- 但是如果想只接管序列化或反序列化其中之一呢蕊连?只接管序列化的過(guò)程就用 JsonSerializer 悬垃,只接管反序列化的過(guò)程就用 JsonDeserializer
- 例如接口返回的數(shù)據(jù),某個(gè)字段是int型甘苍,如果有些情況下給你返了個(gè)空字符串怎么辦
- 用TypeAdapter實(shí)現(xiàn)
class NumTypeAdapter : TypeAdapter<Number>() {
override fun write(out: JsonWriter, value: Number) {
log("numTypeAdapter.write:$value")
out.value(value.toString())
}
override fun read(`in`: JsonReader): Number {
return try {
val str = `in`.nextString()
log("numTypeAdapter.read:$str")
if (str == null || str.isEmpty()) {
return -1
}
NumberFormat.getInstance().parse(str) ?: -1
} catch (e: Exception) {
log("e:$e")
-1
}
}
}
- 用JsonSerializer與JsonDeserializer實(shí)現(xiàn)
class NumJsonSerializer : JsonSerializer<Number> {
override fun serialize(
src: Number?,
typeOfSrc: Type?,
context: JsonSerializationContext?
): JsonElement {
log("typeOfSrc:$typeOfSrc")
return JsonPrimitive(src.toString())
}
}
class NumJsonDeserializer : JsonDeserializer<Number> {
override fun deserialize(
json: JsonElement?,
typeOfT: Type?,
context: JsonDeserializationContext?
): Number {
return try {
log("typeOfT:$typeOfT")
json?.asNumber ?: -1
} catch (e: Exception) {
log("e:${e}")
-1
}
}
}
- 使用測(cè)試
val gson9 = GsonBuilder()
.registerTypeAdapter(Number::class.java, NumTypeAdapter())
.registerTypeHierarchyAdapter(Number::class.java, NumJsonSerializer())
.registerTypeHierarchyAdapter(Number::class.java, NumJsonDeserializer())
.create()
log(gson9.toJson(100, Number::class.java))
log(gson9.toJson(6.66, Number::class.java))
log(gson9.toJson(111111111111111111, Number::class.java))
log(gson9.fromJson("\"\"", Number::class.java))
log(gson9.fromJson("", Number::class.java))
log(gson9.fromJson("88.88", Number::class.java))
log(gson9.fromJson("55", Number::class.java))
log(gson9.fromJson("111111111111111111", Number::class.java))
log(gson9.toJson(100, Int::class.java))
log(gson9.toJson(6.66, Double::class.java))
log(gson9.toJson(111111111111111111, Long::class.java))
log(gson9.fromJson("\"\"", Number::class.java))
log(gson9.fromJson("", Double::class.java))
log(gson9.fromJson("88.88", Double::class.java))
log(gson9.fromJson("55", Int::class.java))
log(gson9.fromJson("111111111111111111", Long::class.java))
- registerTypeAdapter與registerTypeHierarchyAdapter的區(qū)別:
- registerTypeAdapter:支持泛型,不支持繼承
- registerTypeHierarchyAdapter:不支持泛型,支持繼承
- TypeAdapter與 JsonSerializer尝蠕、JsonDeserializer對(duì)比,TypeAdapter效率高,內(nèi)存占用小,支持Stream API
實(shí)戰(zhàn)
- 服務(wù)器返回的數(shù)據(jù)中data字段類(lèi)型不固定载庭,比如請(qǐng)求成功data是一個(gè)List,不成功的時(shí)候是String類(lèi)型看彼,這樣前端在使用泛型解析的時(shí)候,怎么去處理呢囚聚?
val gson11 = GsonBuilder().registerTypeHierarchyAdapter(
MutableList::class.java,
JsonDeserializer { json, typeOfT, context ->
if (json.isJsonArray) {
log("isJsonArray")
val array = json.asJsonArray
val itemType: Type =
(typeOfT as ParameterizedType).actualTypeArguments[0]
val list: MutableList<Any?> = mutableListOf()
for (i in 0 until array.size()) {
val element = array[i]
val item = context.deserialize<Any>(element, itemType)
list.add(item)
}
list
} else {
log("返回空List")
Collections.EMPTY_LIST
}
}).create()
log(gson11.toJson(listOf(UserInfo3())))
val type = object : TypeToken<List<UserInfo3?>?>() {}.type
log(gson11.fromJson("[{\"age\":20,\"emailAddress\":\"xx@qq.com\",\"height\":180,\"man\":true,\"name\":\"ljy\"}]", type))
log(gson11.fromJson("{}", type))
log(gson11.fromJson("暫無(wú)數(shù)據(jù)", type))
TypeAdapterFactory
- 用于創(chuàng)建TypeAdapter的工廠(chǎng)類(lèi)靖榕,通過(guò)對(duì)比Type,確定有沒(méi)有對(duì)應(yīng)的TypeAdapter顽铸,沒(méi)有就返回null茁计,與GsonBuilder.registerTypeAdapterFactory配合使用
- 比如根據(jù)當(dāng)為null時(shí),根據(jù)泛型是String則返回“”,是List則返回空l(shuí)ist
class GsonDefaultAdapterFactory: TypeAdapterFactory {
override fun <T : Any> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? {
if (type.type == String::class.java) {
return createStringAdapter()
}
if (type.rawType == List::class.java || type.rawType == Collection::class.java) {
return createCollectionAdapter(type, gson)
}
return null
}
/**
* null替換成空List
*/
private fun <T : Any> createCollectionAdapter(
type: TypeToken<T>,
gson: Gson
): TypeAdapter<T>? {
val rawType = type.rawType
if (!Collection::class.java.isAssignableFrom(rawType)) {
return null
}
val elementType: Type = `$Gson$Types`.getCollectionElementType(type.type, rawType)
val elementTypeAdapter: TypeAdapter<Any> =
gson.getAdapter(TypeToken.get(elementType)) as TypeAdapter<Any>
return object : TypeAdapter<Collection<Any>>() {
override fun write(writer: JsonWriter, value: Collection<Any>?) {
writer.beginArray()
value?.forEach {
elementTypeAdapter.write(writer, it)
}
writer.endArray()
}
override fun read(reader: JsonReader): Collection<Any> {
val list = mutableListOf<Any>()
// null替換為""
if (reader.peek() == JsonToken.NULL) {
reader.nextNull()
return list
}
reader.beginArray()
while (reader.hasNext()) {
val element = elementTypeAdapter.read(reader)
list.add(element)
}
reader.endArray()
return list
}
} as TypeAdapter<T>
}
/**
* null 替換成空字符串
*/
private fun <T : Any> createStringAdapter(): TypeAdapter<T> {
return object : TypeAdapter<String>() {
override fun write(writer: JsonWriter, value: String?) {
if (value == null) {
writer.value("")
} else {
writer.value(value)
}
}
override fun read(reader: JsonReader): String {
// null替換為""
if (reader.peek() == JsonToken.NULL) {
reader.nextNull()
return ""
}
return reader.nextString()
}
} as TypeAdapter<T>
}
}
//使用
val gson10 = GsonBuilder()
.registerTypeAdapterFactory(GsonDefaultAdapterFactory())
.create()
@JsonAdapter注解
- 用在自定義模型類(lèi)上跋破,接收一個(gè)參數(shù)簸淀,且參數(shù)類(lèi)型必須是TypeAdapter,TypeAdapterFactory,JsonSerializer或JsonDeserializer其中之一
// @JsonAdapter(NumJsonSerializer::class)
// @JsonAdapter(NumJsonDeserializer::class)
// @JsonAdapter(NumTypeAdapter::class)
@JsonAdapter(KotlinAdapterFactory2::class)
data class UserInfo5(
var name: String = "ljy",
private var email: String? = "xxx@qq.com",
private val mobile: String? = "12315",
)
- 使用時(shí)就不用再使用 GsonBuilder去注冊(cè)UserTypeAdapter了
log("UserInfo5:${Gson().toJson(UserInfo5())}")
源碼解析
- 使用時(shí)我們是從fromJson(反序列化) and toJson(序列化)這兩個(gè)最基礎(chǔ)的方法開(kāi)始毒返,那么我們來(lái)點(diǎn)進(jìn)去看看他們是如何實(shí)現(xiàn)的
fromJson方法
- fromJson有多個(gè)重載方法租幕,最終都會(huì)調(diào)用到fromJson(JsonReader reader, Type typeOfT)
public <T> T fromJson(String json, Class<T> classOfT) throws JsonSyntaxException {
//Class<T>轉(zhuǎn)為T(mén)ype
Object object = fromJson(json, (Type) classOfT);
return Primitives.wrap(classOfT).cast(object);
}
public <T> T fromJson(String json, Type typeOfT) throws JsonSyntaxException {
if (json == null) {
return null;
}
//將String包裝為StringReader
StringReader reader = new StringReader(json);
T target = (T) fromJson(reader, typeOfT);
return target;
}
public <T> T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyntaxException {
//將Reader包裝為JsonReader
JsonReader jsonReader = newJsonReader(json);
T object = (T) fromJson(jsonReader, typeOfT);
assertFullConsumption(object, jsonReader);
return object;
}
public <T> T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException {
boolean isEmpty = true;
boolean oldLenient = reader.isLenient();
reader.setLenient(true);
try {
reader.peek();
isEmpty = false;
TypeToken<T> typeToken = (TypeToken<T>) TypeToken.get(typeOfT);
//獲取TypeAdapter
TypeAdapter<T> typeAdapter = getAdapter(typeToken);
T object = typeAdapter.read(reader);
return object;
} catch //。拧簸。劲绪。省略很多異常處理
} finally {
reader.setLenient(oldLenient);
}
}
- 從上面代碼可以看到最終調(diào)用了getAdapter來(lái)根據(jù)typeToken獲取TypeAdapter,再通過(guò)TypeAdapter.read方法最終反序列化數(shù)據(jù),上面的使用詳解中我們有介紹了如何自定義TypeAdapter,所以對(duì)read方法也就不默生了盆赤;
getAdapter方法
- 那么來(lái)看一下getAdapter方法是如何實(shí)現(xiàn)的
public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
//先從緩存ConcurrentHashMap<TypeToken<?>, TypeAdapter<?>> typeTokenCache中取
TypeAdapter<?> cached = typeTokenCache.get(type == null ? NULL_KEY_SURROGATE : type);
if (cached != null) {
return (TypeAdapter<T>) cached;
}
//再?gòu)腡hreadLocal<Map<TypeToken<?>, FutureTypeAdapter<?>>> calls 中取
Map<TypeToken<?>, FutureTypeAdapter<?>> threadCalls = calls.get();
boolean requiresThreadLocalCleanup = false;
if (threadCalls == null) {
threadCalls = new HashMap<TypeToken<?>, FutureTypeAdapter<?>>();
calls.set(threadCalls);
requiresThreadLocalCleanup = true;
}
// the key and value type parameters always agree
FutureTypeAdapter<T> ongoingCall = (FutureTypeAdapter<T>) threadCalls.get(type);
if (ongoingCall != null) {
return ongoingCall;
}
try {
FutureTypeAdapter<T> call = new FutureTypeAdapter<T>();
threadCalls.put(type, call);
//緩存map和ThreadLocal中都沒(méi)有贾富,則循環(huán)List<TypeAdapterFactory> factories 集合
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();
}
}
}
- 其中通過(guò)ThreadLocal緩存TypeAdapter對(duì)象,不同的線(xiàn)程使用緩存來(lái)解析的時(shí)候互不影響
- 通過(guò)上面代碼可以看到最終是在List<TypeAdapterFactory> factories 集合中獲取到TypeAdapter的牺六,factories里面都有啥呢颤枪,我們來(lái)看看Gson構(gòu)造方法中是如何初始化的
Gson的構(gòu)造方法
public Gson() {
this(Excluder.DEFAULT, FieldNamingPolicy.IDENTITY,
Collections.<Type, InstanceCreator<?>>emptyMap(), DEFAULT_SERIALIZE_NULLS,
DEFAULT_COMPLEX_MAP_KEYS, DEFAULT_JSON_NON_EXECUTABLE, DEFAULT_ESCAPE_HTML,
DEFAULT_PRETTY_PRINT, DEFAULT_LENIENT, DEFAULT_SPECIALIZE_FLOAT_VALUES,
LongSerializationPolicy.DEFAULT, null, DateFormat.DEFAULT, DateFormat.DEFAULT,
Collections.<TypeAdapterFactory>emptyList(), Collections.<TypeAdapterFactory>emptyList(),
Collections.<TypeAdapterFactory>emptyList());
}
Gson(。淑际。畏纲。) {
扇住。。盗胀。
List<TypeAdapterFactory> factories = new ArrayList<TypeAdapterFactory>();
factories.add(TypeAdapters.JSON_ELEMENT_FACTORY);
factories.add(ObjectTypeAdapter.FACTORY);
factories.add(excluder);
factories.addAll(factoriesToBeAdded);
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);
factories.add艘蹋。。票灰。//太多了
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中添加了很多預(yù)制的TypeAdapterFactory女阀,我們拿出其中的STRING_FACTORY看一下是如何實(shí)現(xiàn)的
public static final TypeAdapterFactory STRING_FACTORY = newFactory(String.class, STRING);
public static final TypeAdapter<String> STRING = new TypeAdapter<String>() {
@Override
public String read(JsonReader in) throws IOException {
JsonToken peek = in.peek();
if (peek == JsonToken.NULL) {
in.nextNull();
return null;
}
/* coerce booleans to strings for backwards compatibility */
if (peek == JsonToken.BOOLEAN) {
return Boolean.toString(in.nextBoolean());
}
return in.nextString();
}
@Override
public void write(JsonWriter out, String value) throws IOException {
out.value(value);
}
};
- 可以看到其調(diào)用了newFactory方法, 其實(shí)就是判斷一下typeToken.getRawType() == type,就直接返回了入?yún)⒌腡ypeAdapter STRING
public static <TT> TypeAdapterFactory newFactory(
final Class<TT> type, final TypeAdapter<TT> typeAdapter) {
return new TypeAdapterFactory() {
@SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
@Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
return typeToken.getRawType() == type ? (TypeAdapter<T>) typeAdapter : null;
}
@Override public String toString() {
return "Factory[type=" + type.getName() + ",adapter=" + typeAdapter + "]";
}
};
}
- 再回到getAdapter方法屑迂,循環(huán)factories中調(diào)用了factory.create方法浸策,其實(shí)就是上面newFactory中的實(shí)現(xiàn)的TypeAdapterFactory的create方法
- 需要注意的一點(diǎn)是Gson初始化factories時(shí)的順序,首先是各種常用的基礎(chǔ)類(lèi)的TypeAdapterFactory屈糊,最后幾行中添加JsonAdapterAnnotationTypeAdapterFactory對(duì)象在ReflectiveTypeAdapterFactory對(duì)象之前的榛,如果對(duì)實(shí)體類(lèi)使用了@JsonAdapter且指定的適配器存在那么就會(huì)返回@JsonAdapter里指定的適配器而不返回ReflectiveTypeAdapterFactory創(chuàng)建的,這樣我們就可以自己接管后面的解析過(guò)程了
JsonAdapterAnnotationTypeAdapterFactory
- JsonAdapterAnnotationTypeAdapterFactory的create方法如下
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> targetType) {
Class<? super T> rawType = targetType.getRawType();
JsonAdapter annotation = rawType.getAnnotation(JsonAdapter.class);
if (annotation == null) {
return null;
}
return (TypeAdapter<T>) getTypeAdapter(constructorConstructor, gson, targetType, annotation);
}
ReflectiveTypeAdapterFactory
- 沒(méi)有使用@JsonAdapter注解的返回ReflectiveTypeAdapterFactory實(shí)例逻锐,我們看看它的create方法
@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));
}
- create中主要是調(diào)用getBoundFields方法,將實(shí)體類(lèi)中需要解析的字段添加一個(gè)集合里夫晌,在反序列化時(shí)進(jìn)行賦值
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) {
//得到實(shí)體類(lèi)所有的字段
Field[] fields = raw.getDeclaredFields();
for (Field field : fields) {
//字段是否參與反序列化或者序列化過(guò)程
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;
}
- 其中調(diào)用了excludeField來(lái)判斷字段是否參與反序列化或者序列化過(guò)程,實(shí)現(xiàn)如下
public boolean excludeField(Field f, boolean serialize) {
return excludeField(f, serialize, excluder);
}
static boolean excludeField(Field f, boolean serialize, Excluder excluder) {
return !excluder.excludeClass(f.getType(), serialize) && !excluder.excludeField(f, serialize);
}
//excludeClassChecks(clazz)檢查class類(lèi)型是否符合序列化或者反序列化要求,里面用到的Since和Until注解
//excludeClassInStrategy(clazz, serialize)通過(guò)加入自己的策略來(lái)控制字段是否要參與解析
//excluder.excludeField(f, serialize)過(guò)濾字段
public boolean excludeClass(Class<?> clazz, boolean serialize) {
return excludeClassChecks(clazz) ||
excludeClassInStrategy(clazz, serialize);
}
- 回到getBoundFields中昧诱,其調(diào)用了createBoundField來(lái)創(chuàng)建BoundField
createBoundField
private ReflectiveTypeAdapterFactory.BoundField createBoundField(
final Gson context, final Field field, final String name,
final TypeToken<?> fieldType, boolean serialize, boolean deserialize) {
//是否是基本數(shù)據(jù)類(lèi)型
final boolean isPrimitive = Primitives.isPrimitive(fieldType.getRawType());
// special casing primitives here saves ~5% on Android...
//@JsonAdapter注解晓淀,如果實(shí)體類(lèi)某屬性使用了@JsonAdapter,那么該屬性的序列化和反序列化將由指定的適配器接管盏档。
//如果沒(méi)有這會(huì)從Gson初始化中查找對(duì)于的解析適配器
JsonAdapter annotation = field.getAnnotation(JsonAdapter.class);
TypeAdapter<?> mapped = null;
if (annotation != null) {
mapped = jsonAdapterFactory.getTypeAdapter(
constructorConstructor, context, fieldType, annotation);
}
final boolean jsonAdapterPresent = mapped != null;
if (mapped == null) mapped = context.getAdapter(fieldType);
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 {
//typeAdapter.read
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
}
};
}
參考