杰克逊:用不同的模型解析相同的密钥
Jackson: Parse same key with different model
在 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
可以有多种类型,我想从JSON中获取这个字段只有当id是“B”时 .当检索并读取 JSON 时,会抛出一个错误,因为它读取了 ID 为“A”的步骤,但未找到 dateOfBirth
,因此会抛出以下错误:
MistmatchedInputException:无法从 START_OBJECT 令牌中反序列化字符串实例 ...
如果 data
字段与 JSON 格式不匹配,是否可以忽略该字段?
我想阅读 JSON,但唯一与我相关的 data
是与特定 ID 相关的内容!
我会说你最好的选择是为 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)
}
}
您可以直接在class上注册解串器,如下所示:
@JsonDeserialize(using = StepResponseDeserializer.class)
data class StepResponse @JsonCreator constructor(
val status: String,
val id: String,
val data: Data?
)
作为旁注,您可以删除所有 @JsonProperty
注释,因为只有在 Java/Kotlin 属性 名称与 JSON 属性 名字.
在 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
可以有多种类型,我想从JSON中获取这个字段只有当id是“B”时 .当检索并读取 JSON 时,会抛出一个错误,因为它读取了 ID 为“A”的步骤,但未找到 dateOfBirth
,因此会抛出以下错误:
MistmatchedInputException:无法从 START_OBJECT 令牌中反序列化字符串实例 ...
如果 data
字段与 JSON 格式不匹配,是否可以忽略该字段?
我想阅读 JSON,但唯一与我相关的 data
是与特定 ID 相关的内容!
我会说你最好的选择是为 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)
}
}
您可以直接在class上注册解串器,如下所示:
@JsonDeserialize(using = StepResponseDeserializer.class)
data class StepResponse @JsonCreator constructor(
val status: String,
val id: String,
val data: Data?
)
作为旁注,您可以删除所有 @JsonProperty
注释,因为只有在 Java/Kotlin 属性 名称与 JSON 属性 名字.