【问题标题】:Same SerializedName for two different data types sometimes, but with Kotlin有时两种不同的数据类型使用相同的 SerializedName,但使用 Kotlin
【发布时间】:2020-06-01 23:56:57
【问题描述】:

不幸的是,我从中提取的 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)
}

如何处理“medium”可以是字符串数组或 Int 的两种情况?

【问题讨论】:

    标签: json kotlin types gson derivative


    【解决方案1】:

    您可以为这种情况编写自定义 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 实例来反序列化你的对象

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-12-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-14
      相关资源
      最近更新 更多