我有一个Kotlin数据类,它的arg可以是Object或Array。有没有一种方法可以将字符串反序列化到此类中,并且不在乎是否不是Array,而是以某种方式将其放入一个由一个组成的数组中?
data class Game(var name:List<NameItem>)
data class NameItem(var title: String, var id: Int)
数据可以以单个对象或对象数组的方式返回(我无法控制数据,因为它是第三方数据。
jsonString = "{"game":{"name":{"title":"GameName","id":22}}}"
jsonString = "{"game":{"name":[{"title":"GameName","id":22},{"title":"GameName2","id":23}]}}"
game: Game? = Gson().fromJson(jsonString Game::class.java)
答案 0 :(得分:2)
您必须编写自定义JsonDeserializer
。两者或您的班级应具有相同的父班级。然后,为此特定类型编写自定义JsonDeserializer
。
例如:
sealed class GameParent() {
data class Game(val name: String): GameParent()
data class GameList(val games: List<Game>): GameParent()
}
class GameDeserializer : JsonDeserializer<GameParent> {
override fun deserialize(json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext?): GameParent {
with(json) {
if(isJsonObject) {
// parse as Game
}
if(isJsonArray) {
// parse as GameList
}
}
}
}
然后,必须在您的GsonBuilder
中注册此自定义JsonDeserializer
:
gsonBuilder.registerTypeAdapter(GameParent::class.java, GameDeserializer());
现在,只要您的Gson
期望GameParent
将使用注册的反序列化器。
答案 1 :(得分:1)
我对解决任务的建议
我的解决方案,如果名称是对象,则将其替换为数组
data class Game(var name:List<NameItem> )
data class NameItem(var title: String, var id: Int)
fun main(args: Array<String>) {
var json = "{\"game\":{\"name\":[{\"title\":\"game 1\",\"id\":1},{\"title\":\"game 2\",\"id\":2}]}}"
println(useJsonParser(json)) //Game(name=[NameItem(title=game 1, id=1), NameItem(title=game 2, id=2)])
json = "{\"game\":{\"name\":[{\"title\":\"game 1\",\"id\":1}]}}"
println(useJsonParser(json)) //Game(name=[NameItem(title=game 1, id=1), NameItem(title=game 2, id=2)])
json = "{\"game\":{\"name\":{\"title\":\"game 1\",\"id\":1}}}" // not array
println(useJsonParser(json)) //Game(name=[NameItem(title=game 1, id=1)])
}
版本1-创建并注册了适配器link @Cililing
fun useJsonParser(json: String): Game? {
val gson = GsonBuilder().registerTypeAdapter(Game::class.java, GameDeserializer()).create()
return gson.fromJson(json, Game::class.java)
}
class GameDeserializer : JsonDeserializer<Game?> {
override fun deserialize(json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext?): Game? {
val gameJson = json!!.asJsonObject.get("game")
if (gameJson.isJsonObject) {
val jsonName = gameJson.asJsonObject["name"]
val list = if (jsonName.isJsonObject) {
arrayOf(Gson().fromJson(jsonName, NameItem::class.java))
} else {
val fromJson = Gson().fromJson(jsonName, Array<NameItem>::class.java)
fromJson
}.toList()
return Game(list)
}
return null
}
}
第2版-处理响应
fun useJsonParser(json:String):Game?{
val jsonObject = JsonParser().parse(json).asJsonObject.get("game")
if(jsonObject.asJsonObject["name"].isJsonObject){
val jsonName = jsonObject.asJsonObject["name"].asJsonObject
val array = JsonArray()
array.add(jsonName)
jsonObject.asJsonObject.add("name", array) // rewrite origin JSON
}
return Gson().fromJson(jsonObject, Game::class.java)
}
vesrion 3-添加适配器TypeToken>()
fun useJsonParser(json: String): Game? {
val type = object : TypeToken<MutableList<NameItem>>() {}.type
val gson = GsonBuilder().registerTypeAdapter(type, NameItemDeserializer()).create()
return gson.fromJson(JsonParser().parse(json).asJsonObject.get("game"), Game::class.java)
}
class NameItemDeserializer : JsonDeserializer<List<NameItem>?> {
override fun deserialize(json: JsonElement, type: Type, context: JsonDeserializationContext?): List<NameItem>? {
with(json){
return if(isJsonObject){
arrayListOf(Gson().fromJson(this,NameItem::class.java))
}else{
Gson().fromJson(this,Array<NameItem>::class.java).toList()
}
}
}
}