如何用不同的继承人反序列化 JSON
How to deserialize JSON with different heirs
有几种json,我举两种为例:
{
"name": "dataUpdated",
"version": 102,
"eventTime": "2021-06-24",
"payload": {
"id": 158420,
"name": 446970,
"date": "2021-06-16",
"type": "A"
}
{
"name": "dataError",
"version": 102,
"eventTime": "2021-06-25",
"payload": {
"error": 666,
"errorMsg": "forbidden"
}
只有有效载荷的结构发生了变化
我有一个 class MessageDto
class MessageDto {
@JsonProperty("name")
String name
@JsonProperty("version")
Integer version
@JsonProperty("eventTime")
String eventTime
@JsonProperty("payload")
Payload payload
}
Class Payload 是空的,我只是用它作为标记,并从中继承了两个class:
DataUpdatedDto extends Payload {
@JsonProperty("id")
BigInteger id
@JsonProperty("name")
String name
@JsonProperty("date")
String date
@JsonProperty("type")
String type
}
DataErrorDto extends Payload {
@JsonProperty("error")
Integer error
@JsonProperty("errorMsg")
String errorMsg
}
如何向反序列化器解释我要反序列化 Payload 的哪个后代?
您需要设置以下内容:
- 使用
@JsonTypeInfo
设置应用某些策略的机制
派遣到某些实施 classes
include=JsonTypeInfo.As.EXTERNAL_PROPERTY
因为你想要的
dispatch 不是 inside payload,而是在同一层
地图
use=JsonTypeInfo.Id.NAME, property="name"
从中读取值
name
属性 进行调度
- 使用
@JsonSubTypes
和 @JsonSubTypes.Type
设置
- 例如
@JsonSubTypes.Type(value=DataUpdatedDto, name="dataUpdated")
将 class DataUpdatedDto
与值相关联
dataUpdated
在父映射中
完整示例
@Grab('com.fasterxml.jackson.core:jackson-databind:2.12.4')
import com.fasterxml.jackson.annotation.*
import com.fasterxml.jackson.databind.*
class MessageDto {
@JsonProperty("name")
String name
@JsonProperty("version")
Integer version
@JsonProperty("eventTime")
String eventTime
@JsonProperty("payload")
@JsonTypeInfo(include=JsonTypeInfo.As.EXTERNAL_PROPERTY, use=JsonTypeInfo.Id.NAME, property="name")
@JsonSubTypes([
@JsonSubTypes.Type(value=DataUpdatedDto, name="dataUpdated"),
@JsonSubTypes.Type(value=DataErrorDto, name="dataError")
])
Payload payload
}
interface Payload {}
class DataUpdatedDto implements Payload {
@JsonProperty("id")
BigInteger id
@JsonProperty("name")
String name
@JsonProperty("date")
String date
@JsonProperty("type")
String type
}
class DataErrorDto implements Payload {
@JsonProperty("error")
Integer error
@JsonProperty("errorMsg")
String errorMsg
}
def objectMapper = new ObjectMapper()
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
def updated = objectMapper.readValue("""
{
"name": "dataUpdated",
"version": 102,
"eventTime": "2021-06-24",
"payload": {
"id": 158420,
"name": 446970,
"date": "2021-06-16",
"type": "A"
}
}
""", MessageDto)
assert updated.payload instanceof DataUpdatedDto
def error = objectMapper.readValue("""
{
"name": "dataError",
"version": 102,
"eventTime": "2021-06-25",
"payload": {
"error": 666,
"errorMsg": "forbidden"
}
}
""", MessageDto)
assert error.payload instanceof DataErrorDto
有几种json,我举两种为例:
{
"name": "dataUpdated",
"version": 102,
"eventTime": "2021-06-24",
"payload": {
"id": 158420,
"name": 446970,
"date": "2021-06-16",
"type": "A"
}
{
"name": "dataError",
"version": 102,
"eventTime": "2021-06-25",
"payload": {
"error": 666,
"errorMsg": "forbidden"
}
只有有效载荷的结构发生了变化
我有一个 class MessageDto
class MessageDto {
@JsonProperty("name")
String name
@JsonProperty("version")
Integer version
@JsonProperty("eventTime")
String eventTime
@JsonProperty("payload")
Payload payload
}
Class Payload 是空的,我只是用它作为标记,并从中继承了两个class:
DataUpdatedDto extends Payload {
@JsonProperty("id")
BigInteger id
@JsonProperty("name")
String name
@JsonProperty("date")
String date
@JsonProperty("type")
String type
}
DataErrorDto extends Payload {
@JsonProperty("error")
Integer error
@JsonProperty("errorMsg")
String errorMsg
}
如何向反序列化器解释我要反序列化 Payload 的哪个后代?
您需要设置以下内容:
- 使用
@JsonTypeInfo
设置应用某些策略的机制 派遣到某些实施 classesinclude=JsonTypeInfo.As.EXTERNAL_PROPERTY
因为你想要的 dispatch 不是 inside payload,而是在同一层 地图use=JsonTypeInfo.Id.NAME, property="name"
从中读取值name
属性 进行调度
- 使用
@JsonSubTypes
和@JsonSubTypes.Type
设置- 例如
@JsonSubTypes.Type(value=DataUpdatedDto, name="dataUpdated")
将 classDataUpdatedDto
与值相关联dataUpdated
在父映射中
- 例如
完整示例
@Grab('com.fasterxml.jackson.core:jackson-databind:2.12.4')
import com.fasterxml.jackson.annotation.*
import com.fasterxml.jackson.databind.*
class MessageDto {
@JsonProperty("name")
String name
@JsonProperty("version")
Integer version
@JsonProperty("eventTime")
String eventTime
@JsonProperty("payload")
@JsonTypeInfo(include=JsonTypeInfo.As.EXTERNAL_PROPERTY, use=JsonTypeInfo.Id.NAME, property="name")
@JsonSubTypes([
@JsonSubTypes.Type(value=DataUpdatedDto, name="dataUpdated"),
@JsonSubTypes.Type(value=DataErrorDto, name="dataError")
])
Payload payload
}
interface Payload {}
class DataUpdatedDto implements Payload {
@JsonProperty("id")
BigInteger id
@JsonProperty("name")
String name
@JsonProperty("date")
String date
@JsonProperty("type")
String type
}
class DataErrorDto implements Payload {
@JsonProperty("error")
Integer error
@JsonProperty("errorMsg")
String errorMsg
}
def objectMapper = new ObjectMapper()
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
def updated = objectMapper.readValue("""
{
"name": "dataUpdated",
"version": 102,
"eventTime": "2021-06-24",
"payload": {
"id": 158420,
"name": 446970,
"date": "2021-06-16",
"type": "A"
}
}
""", MessageDto)
assert updated.payload instanceof DataUpdatedDto
def error = objectMapper.readValue("""
{
"name": "dataError",
"version": 102,
"eventTime": "2021-06-25",
"payload": {
"error": 666,
"errorMsg": "forbidden"
}
}
""", MessageDto)
assert error.payload instanceof DataErrorDto