有时为两个不同的数据类型使用相同的SerializedName,但使用Kotlin

问题描述 投票:0回答:1

不幸的是,我从JSON文件中提取的节点具有相同的变量名,但可以随机具有两种不同的数据类型。当我拨打网络电话(使用gson)时,出现错误:

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected a BEGIN_ARRAY but was int at line 1 column 5344 path $[1].medium

JSON看起来像

{
  "title": "Live JSON generator",
  "url": google.com,
  "medium": ["chicken", "radio", "room"] 
}
//However sometimes medium can be:
"medium": 259

我的序列化类如下:

data class SearchItem(
    @SerializedName("title") var title: String,
    @SerializedName("url") var urlStr: String,
    @SerializedName("medium") val medium: List<String>? = null
) : Serializable {}

我进行网络通话的方式是这样的:

private val api: P1Api

fun onItemClicked(searchItem: SearchItem) {
   api.getCollections { response, error ->
      response.toString()
      val searchItems: List<SearchItem> = Util.gson?.fromJson<List<SearchItem>>(
                           response.get("results").toString()
                           , object : TypeToken<List<SearchItem>>() {}.type)?.toList()!!
...
      doStuffWithSearchItems(searchItems)
}

我如何处理“中号”可以是字符串数组还是整数的两种情况?

json kotlin types gson derivative
1个回答
0
投票

您可以为这种情况编写自定义的JsonDeserializer:

class SearchItemCustomDeserializer: JsonDeserializer<SearchItem> {
    override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): SearchItem {
        val obj = json.asJsonObject
        val title = obj.get("title").asString
        val url = obj.get("url").asString
        val mediumProp = obj.get("medium")
        val medium = if(mediumProp.isJsonArray) {
            mediumProp.asJsonArray.map { it.asString }
        } else {
            listOf(mediumProp.asString)
        }
        return SearchItem(
            title = title,
            urlStr = url,
            medium = medium
        )
    }
}

使用此类,您可以“手动”将json反序列化为对象。对于中等属性,我们检查此数组或具有函数mediumProp.isJsonArray的简单json原语。如果答案是肯定的,则将字段反序列化为字符串的json数组mediumProp.asJsonArray.map { it.asString }否则将字段反序列化为字符串。

然后,我们使用方法registerTypeAdapter在GsonBuilder上注册自定义SearchItemCustomDeserializer,>

val gson = GsonBuilder()
    .registerTypeAdapter(SearchItem::class.java, SearchItemCustomDeserializer())
    .create()

然后,您可以使用此gson实例反序列化您的对象

© www.soinside.com 2019 - 2024. All rights reserved.