网创优客建站品牌官网
为成都网站建设公司企业提供高品质网站建设
热线:028-86922220
成都专业网站建设公司

定制建站费用3500元

符合中小企业对网站设计、功能常规化式的企业展示型网站建设

成都品牌网站建设

品牌网站建设费用6000元

本套餐主要针对企业品牌型网站、中高端设计、前端互动体验...

成都商城网站建设

商城网站建设费用8000元

商城网站建设因基本功能的需求不同费用上面也有很大的差别...

成都微信网站建设

手机微信网站建站3000元

手机微信网站开发、微信官网、微信商城网站...

建站知识

当前位置:首页 > 建站知识

Jackson不修改父类而实现多态解析-创新互联

前言

众所周知 jackson 可以如下进行多态处理

创新互联专业为企业提供宏伟网站建设、宏伟做网站、宏伟网站设计、宏伟网站制作等企业网站建设、网页设计与制作、宏伟企业网站模板建站服务,十余年宏伟做网站经验,不只是建网站,更提供有价值的思路和整体网络服务。
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonSubTypes(value = {
        @JsonSubTypes.Type(value = FirstChild.class, name = "first-child"),
        @JsonSubTypes.Type(value = SecondChild.class, name = "second-child"),
})
public interface Parent {
}

@Data
public static class FirstChild implements Parent {
    private String foo;
}

@Data
public static class SecondChild implements Parent {
    private String bar;
}

序列化时 jackson 会读取 @JsonSubTypes 的属性, 最终输出如:

{
    "type": "first-child",
    "foo": "hello, world"
}

反序列化时 jackson 通过 JSON 中的 "type" 属性知道该使用哪一个子类.

问题

当新增一个子类型时, 必须修改父类型的 @JsonSubTypes 注解, 否则不生效

首先是 不够优雅,

更严重的是 如果父类是外部依赖, 我们根本不能修改, 怎么办?

这个问题在 GitHub 中也有讨论, 不过最终没有下文.

解决方案

既然没有现成的方案, 而且 Jackson 的模块化做的很好, 不如自己造个轮子, 其实实际很简单: 通过 SPI 把子类注册进 Jackson 就行. 当然不一定是 SPI, 也可以是 classgraph 等.

今天就厚着脸皮分享一下自己造的轮子: jackson-modules-dynamic-subtype

以最简方式演示:

io.github.black-06.jacksonjackson-modules-dynamic-subtype2.14.0
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
public interface Parent {
}

@Data
@AutoService(Parent.class)
@JsonSubType("first-child")
public static class FirstChild implements Parent {
    private String foo;
}
  • 父类上的 @JsonTypeInfo 仍必须有

  • @AutoService 注解是谷歌 auto 的, 用来自动生成 SPI 所需的 META-INF/services/package.Parent 文件, 具体可见 auto/service at main · google/auto (github.com)

  • @JsonSubType 是轮子里头发明的, 与 @JsonSubTypes 的区别是, 它注解在子类型上.

然后注册模块:

PS. 在 Spring Boot 中它会自动注册, 可以跳过这一步

import io.github.black.jackson.DynamicSubtypeModule;

ObjectMapper mapper = new ObjectMapper().registerModule(new DynamicSubtypeModule());

简简单单.

其他:
  • 轮子里面的 ServiceLoad 是我根据 JDK 8 重写的, 只返回 Class 而不返回 Instance. 如果它工作的不是很正常, 考虑调用 module.setUseStandardServiceLoader(true) 使用标准库的 Loader.

  • 如果你不喜欢 SPI, 可以自行想办法获取所有字类, 并手动调用 module.registerTypes 将其注册进去.

最后, 如果这个轮子帮到了你, 求一个 star~

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


标题名称:Jackson不修改父类而实现多态解析-创新互联
URL网址:http://bjjierui.cn/article/deohco.html

其他资讯