Класс данных Либо Объект, либо Массив - PullRequest
0 голосов
/ 05 марта 2019

У меня есть класс данных Kotlin, у которого есть аргумент, который может быть либо Object, либо Array.Есть ли способ десериализации строки в этот класс и не заботиться, если не массив, а каким-то образом получить его в массив из одного?массив объектов (я не имею никакого контроля над данными, так как это сторонние данные.

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)

Ответы [ 2 ]

0 голосов
/ 05 марта 2019

мои предложения по решению вашей задачи

мое решение, если имя объекта, замените его массивами

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 - создано и адаптер реестра ссылка @ 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()
            }
        }
    }
}
0 голосов
/ 05 марта 2019

Вы должны написать пользовательский 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 будет использовать зарегистрированный десериализатор.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...