Jackson处理抽象类的序列化和反序列化
需求
现在有这样的需求:
- 在controller接口层,@RequestBody接收的是抽象类,@ResponseBody也是抽象类。controller根据请求参数反序列化成子类对象,返回时返回子类对象。
- MongoDB在新增数据时使用的是抽象类,查询返回结果也是抽象类。
默认情况,抽象类是无法完成序列化和反序列化的。那怎么实现呢?
现在有这样的类结果:
controller方法
@PostMapping
public ResponseEntity add(@RequestBody AbstractItem abstractItem) {
AbstractItem item = itemService.add(abstractItem);
return ResponseEntity.ok(item);
}
MongoDb新增
public AbstractItem findById(String id) {
return mongoTemplate.findById(id, AbstractItem.class);
}
实现
这时候就用到了@JsonTypeInfo
的 use
属性表示使用哪种信息来作为 Json 对应的实际子类的标识符和@JsonSubTypes
注解来指定逻辑名称和子类的映射关系.
如下所示:
@Data
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME)
@JsonSubTypes({
@JsonSubTypes.Type(value = DefaultItem.class, name = "item"),
@JsonSubTypes.Type(value = DefaultLayoutRow.class, name = "row"),
})
public abstract class AbstractItem implements Item {
@Id
private String id;
private String name;
}
@Data
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME)
@JsonSubTypes({
@JsonSubTypes.Type(value = DefaultLayoutRow.class, name = "row")
})
public abstract class AbstractLayoutRow extends AbstractItem implements LayoutRow {
private Integer gutter;
public AbstractLayoutRow() {
}
public AbstractLayoutRow(int gutter) {
this.gutter = gutter;
}
}
@Data
@NoArgsConstructor
@JsonTypeName(value = "item")
@Document(collection = "form_item")
@CompoundIndexes(@CompoundIndex(def = "{'group': 1}"))
public class DefaultItem extends AbstractItem {
@ApiModelProperty("标签名")
private String label;
@ApiModelProperty(value = "模型", notes = "字段存值的key,及v-model的值")
private String model;
private String desc;
@JsonTypeName(value = "row")
public class DefaultLayoutRow extends AbstractLayoutRow {
private List<AbstractLayoutCol> columns;
public DefaultLayoutRow() {
}
public DefaultLayoutRow(List<AbstractLayoutCol> columns) {
this.columns = columns;
}
public DefaultLayoutRow(int gutter, List<AbstractLayoutCol> columns) {
super(gutter);
this.columns = columns;
}
public List<AbstractLayoutCol> getColumns() {
return columns;
}
public void setColumns(List<AbstractLayoutCol> columns) {
this.columns = columns;
}
}
JsonTypeInfo.Id
public static enum Id {
NONE((String)null),
CLASS("@class"),
MINIMAL_CLASS("@c"),
NAME("@type"),
CUSTOM((String)null);
}
有五种类型。
CLASS("@class")
: 表示使用权限定类名来表示Json对应的类型,并且会在序列化的Json中插入一个key为@class
的信息,值为类的全限定名。MINIMAL_CLASS("@c")
: 与Class
不同,它不适用全限定名,而是根据子类来计算出应该是使用单纯的类名,还是包含一部分的包名,并且最终的值前会加一个“.” 。NAME("@type")
:标识表示使用逻辑名称标识Json对应的类型。默认是类名。也可以使用@JsonSubTypes
注解 来指定逻辑名称和子类的映射关系。@JsonSubTypes.Type
注解的 name 属性没有指定时,Jackson 会查找这个类上的@JsonTypeName
注解的值用作 name ;如果也不存在,就会使用类名。
参考:https://blog.csdn.net/weixin_33574009/article/details/113491273