【问题标题】:Jackson: Parse same key with different model杰克逊:用不同的模型解析相同的密钥
【发布时间】:2022-01-24 17:45:07
【问题描述】:

在 Kotlin 中,我使用 jackson (fasterxml) 来解析端点响应 (JSON)。它看起来像这样:

{
...
steps: [
   {
      "status":200,
      "id":"A",
      "data":{
         "score":"10"
      }
   },
   {
      "status":200,
      "id":"B",
      "data": {
         "dateOfBirth":"10-09-1994",
         "fullname": "Peter",
         ...
      }
   },
   {
      "status":200,
      "id":"C",
      "data": {
         "dateOfBirth": {
             "value": "10-03-1993"
          },
         ...
      }
   },
]
...
}

我的代码如下所示:


...
response.readEntity(DocumentResponse::class.java)
...



@JsonIgnoreProperties(ignoreUnknown = true)
data class DocumentResponse @JsonCreator constructor(
    @JsonProperty("steps")
    val steps: List<StepResponse>
) 

data class StepResponse @JsonCreator constructor(
    @JsonProperty("status")
    val status: String,
    @JsonProperty("id")
    val id: String,
    @JsonProperty("data")
    val data: Data?
)

@JsonIgnoreProperties(ignoreUnknown = true)
class Data @JsonCreator constructor(
    @JsonProperty("dateOfBirth")
    val dateOfBirth: String?,
    @JsonProperty("fullName")
    val fullName: String?,
    @JsonProperty("dni")
    val dni: String?,
    ...
) 

问题是data 可以有多种类型,我只想在 id 为“B”时从 JSON 中获取该字段。当 JSON 被检索并读取时,会抛出错误,因为它读取 id 为“A”的 step 并且找不到 dateOfBirth,因此会抛出以下错误:

MistmatchedInputException:无法从 START_OBJECT 令牌中反序列化字符串实例...

如果字段data与JSON格式不匹配,是否可以忽略它? 我想阅读 JSON,但唯一与我相关的 data 是与特定 id 相关的那个!

【问题讨论】:

    标签: json kotlin jackson fasterxml


    【解决方案1】:

    我想说你最好的选择是为StepResponse 使用自定义反序列化器:

    import com.fasterxml.jackson.databind.deser.std.StdDeserializer
    import com.fasterxml.jackson.core.JsonParser
    import com.fasterxml.jackson.databind.DeserializationContext
    import com.fasterxml.jackson.databind.JsonNode
    
    class StepResponseDeserializer constructor(vc: Class<*>? = null) : StdDeserializer<StepResponse>(vc) {
        override fun deserialize(jp: JsonParser, ctxt: DeserializationContext): StepResponse {
            val node = jp.codec.readTree<JsonNode>(jp)
            val status = node["status"].asText()
            val id = node["id"].asText()
    
            val data = if ("B" == id) {
                val dataNode = node["data"]
                val dateOfBirth = dataNode["status"].asText()
                val fullName = dataNode["fullName"].asText()
                val dni = dataNode["dni"].asText()
                Data(dateOfBirth, fullName, dni)
            } else null
    
            return StepResponse(status, id, data)
        }
    }
    

    你可以直接在类上注册反序列化器,如下:

    @JsonDeserialize(using = StepResponseDeserializer.class)
    data class StepResponse @JsonCreator constructor(
        val status: String,
        val id: String,
        val data: Data?
    )
    

    附带说明,您可以删除所有 @JsonProperty 注释,因为它们仅在 Java/Kotlin 属性名称与 JSON 属性名称不匹配时才需要。

    【讨论】:

    • 谢谢!它奏效了。
    • 很高兴能帮上忙!
    猜你喜欢
    • 2018-04-20
    • 2019-07-27
    • 2014-08-22
    • 2019-11-25
    • 2014-06-17
    • 1970-01-01
    • 1970-01-01
    • 2020-10-16
    • 2015-08-19
    相关资源
    最近更新 更多