惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
Schneier on Security
博客园 - 【当耐特】
人人都是产品经理
人人都是产品经理
大猫的无限游戏
大猫的无限游戏
Last Week in AI
Last Week in AI
IT之家
IT之家
V
V2EX
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
博客园 - 叶小钗
Martin Fowler
Martin Fowler
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
M
MIT News - Artificial intelligence
博客园 - 聂微东
MyScale Blog
MyScale Blog
云风的 BLOG
云风的 BLOG
The Cloudflare Blog
WordPress大学
WordPress大学
Microsoft Azure Blog
Microsoft Azure Blog
阮一峰的网络日志
阮一峰的网络日志
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园 - 三生石上(FineUI控件)
Cyberwarzone
Cyberwarzone
Scott Helme
Scott Helme
H
Help Net Security
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
The GitHub Blog
The GitHub Blog
Cisco Talos Blog
Cisco Talos Blog
D
DataBreaches.Net
P
Palo Alto Networks Blog
T
Threatpost
P
Privacy & Cybersecurity Law Blog
L
LINUX DO - 最新话题
Know Your Adversary
Know Your Adversary
C
CXSECURITY Database RSS Feed - CXSecurity.com
B
Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
P
Proofpoint News Feed
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Cloudbric
Cloudbric
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
N
News and Events Feed by Topic
T
The Blog of Author Tim Ferriss
L
Lohrmann on Cybersecurity
量子位
Security Latest
Security Latest
Google DeepMind News
Google DeepMind News
Y
Y Combinator Blog
aimingoo的专栏
aimingoo的专栏
Forbes - Security
Forbes - Security
T
Tailwind CSS Blog

Moon's Blog

Java内存 | Moon's Blog Spring Data JPA | Moon's Blog Spring Boot的Java Config | Moon's Blog Java知识点 | Moon's Blog Spring Boot知识点 | Moon's Blog Java异常机制 | Moon's Blog Java的类加载器 | Moon's Blog JVM类加载机制 | Moon's Blog 单体架构与微服务架构 | Moon's Blog 424.替换后的最长重复字符 | Moon's Blog 888.公平的糖果棒交换 | Moon's Blog 839.相似字符串组 | Moon's Blog 778.水位上升的泳池中游泳 | Moon's Blog 1631.最小体力消耗路径 | Moon's Blog 724.寻找数组的中心索引 | Moon's Blog 使用Jackson库实现日期序列化 | Moon's Blog Spring Boot+InfluxDB实现日志管理 | Moon's Blog Java多态+工厂模式实现服务调用 | Moon's Blog 为Spring Boot项目生成OpenAPI3.0文档 | Moon's Blog
使用Jackson库实现Java多态解析 | Moon's Blog
Moon Lou · 2020-09-19 · via Moon's Blog

Jackson是一个Java的用来处理JSON格式数据的类库,性能非常好。在项目开发中,使用Jackson库的@JsonTypeInfo和@JsonSubTypes注解实现Java多态解析,这里做一个记录。

一、需求背景

在项目开发中,model层的Channel类是一个多态的实现,Channel是一个抽象基类,其有两个子类DatasourceChannel和ServiceChannel。底层的数据库采用MongoDB,因此Channel的所有对象都是在一张表(collection)上的。这样的设计(多态思想)非常优雅,因为只需要面向接口(抽象类)编程而非面向实现(子类)编程。

  • 序列化:Java对象转化为JSON格式数据(而后持久化在数据库中)
  • 反序列化:通过JSON格式数据创建对应的Java对象

在默认的情况下,Java对象和序列化后的JSON格式数据的属性都是一样的。但是在Channel的多态实现下,需要具体的类型信息(子类)指导反序列化(因为两个子类的属性集是不同的)。通过Jackson库的@JsonTypeInfo与@JsonSubTypes注解,可以在序列化时,保存具体的类型信息到JSON数据中,当JSON反序列到Java对象时,就可以根据具体类型信息创建正确的Java对象。

  • @JsonTypeInfo:指明类型信息字段
  • @JsonSubTypes:指明不同类型信息分别对应的子类

二、源代码

1. 抽象基类Channel.java

@Data
@NoArgsConstructor
@Document(collection = "channel")
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = ServiceChannel.class, name = "Service"),
@JsonSubTypes.Type(value = DatasourceChannel.class, name = "DataSource"),
})
@Slf4j
public abstract class Channel {
@Id
protected String id;

@NotBlank
protected String ownerId;

protected List<TransformRule> transformRules;

protected FusionRule fusionRule;

protected String description;

abstract public ChannelDTO convert2DTO();

abstract void doDataDistribution(String message);

public abstract void doCompletion();
}

@JsonTypeInfo指明了类型信息字段为type,@JsonSubTypes指明子类ServiceChannel的类型信息为“Service”,子类DatasourceChannel的类型信息为“DataSource”。

类型信息字段type不属于Channel对象中的属性,它只存在于序列化后的JSON数据中。举个例子,一个普通的ServiceChannel对象序列化为JSON数据时,在JSON数据中会多出一个type属性:*”type” : “Service”*。如果从数据库中拿出这条JSON数据,反序列化为Java对象时,会遵循这个type字段的指导,按照子类ServiceChannel的属性集去构造对应的ServiceChannel对象,而构造成功的ServiceChannel对象中,不会出现该type字段。

2. 子类DatasourceChannel.java

@Data
@NoArgsConstructor
public class DatasourceChannel extends Channel{
@NotBlank
private String datasourceId;

@Builder
public DatasourceChannel(String id, String ownerId, List<TransformRule> transformRules, FusionRule fusionRule, String description, String datasourceId){
super.id = id;
super.ownerId = ownerId;
this.transformRules = transformRules;
this.fusionRule = fusionRule;
this.description = description;
this.datasourceId = datasourceId;
}
}

3. 子类ServiceChannel.java

@Data
@NoArgsConstructor
@Slf4j
public class ServiceChannel extends Channel{
@NotBlank
private String serviceId;

private String serviceName;

@NotBlank
private String apiId;

private String apiPath;

private HttpMethod apiMethod;

@NotBlank
private String datasourceId;

@NotBlank
private String processId;

@Builder
public ServiceChannel(String id, String ownerId, String serviceId, String apiId, List<TransformRule> transformRules, FusionRule fusionRule, String description, String processId, String datasourceId){
super.id = id;
super.ownerId = ownerId;
this.serviceId = serviceId;
this.apiId = apiId;
this.transformRules = transformRules;
this.fusionRule = fusionRule;
this.description = description;
this.processId = processId;
this.datasourceId = datasourceId;
}
}

版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Moon's Blog