方法有很多,你可以自己拿responseBody
里的json
,一個個字段自己解析;也可以給okhttp
添加攔截器來處理response內容。
這里提供一種簡便的方法。
Gson
在反序列化的時候,默認是將{}
轉成LinkedTreeMap
,[]
轉成ArrayList
,value是數字的全部定義為了double。
如果后端返回格式不規矩或者會變化的時候,將bean里定義的是Any
或*
即可
比如有時返回的是這樣
image.png
有時是這樣
image.png
可以看到
event
雖然都是個數組,可里面的內容完全就不一樣,于是我就定義倆個data class
,分別為ZulipMessage
和DelMsgEventDTO
data class ZulipEventDTO(
val events: List<LinkedTreeMap<String,Any>>
)
event
定義是一個集合,泛型就是Gson
默認的LinkedTreeMap<String,Any>
,這樣不管是那種數據都可以接受到。并且存入map中。
解析的時候,根據event.type
的類型,解析成不同的類。
private val parseMapGson = GsonBuilder().enableComplexMapKeySerialization().create() //重點行
eventDTO.events.forEach { event ->
when (event["type"]) {
//根據type類型,解析成不同的類
ZulipConst.EVENT_TYPE_MESSAGE -> {
val messageJson = parseMapGson.toJson(event[ZulipConst.EVENT_TYPE_MESSAGE]) // 先將LinkedList轉成json
val zulipMessage = parseMapGson.fromJson<ZulipMessage>(messageJson, ZulipMessage::class.java) //再根據類型轉成bean對象
saveMsg2Database(zulipMessage)
}
ZulipConst.EVENT_TYPE_DELETE_MESSAGE -> {
val messageJson = parseMapGson.toJson(event[ZulipConst.EVENT_TYPE_DELETE_MESSAGE])
val delMsgEventDTO = parseMapGson.fromJson<ZulipMessage>(messageJson, DelMsgEventDTO::class.java)
delMsgFromDb(delMsgEventDTO)
}
else -> {
}
}
// Any被轉成LinkedTreeMap時,所有數字都是double
val eventId = (event["id"] as Double).toLong()
if (eventId > lastEventId) {
lastEventId = eventId
}
}
總結:有type
能幫忙判斷返回數據類型的,那就根據類型定義不同的類,先用LinkedTreeMap
接住數據,再根據類型轉就是了。
如果沒有type
這種字段,完全無法預料返回的是個什么,那不妨就從LinkedTreeMap中直接取數據。