【工作中问题解决实践 十二】使用@JsonTypeInfo实现请求数据对象多态

简介: 【工作中问题解决实践 十二】使用@JsonTypeInfo实现请求数据对象多态

最近在处理接口请求进行数据写入的一个case时,我希望上游只使用我一个写入接口去实现不同类型的数据写入,而上游的数据写入Model是各不相同的,这就要求我接口的一个对象可以应对上游不同类型对象的写入请求。关于Jackson的概念不再赘述,参照这篇Blog:【Spring MVC学习笔记 五】SpringMVC框架整合Jackson工具

模拟代码实现示例

为了代码保密,同样用示例的方式进行介绍

基类及子类

接收请求的基类

package com.example.springboot.controller.model;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import lombok.Data;
import java.time.LocalDateTime;
/**
 * @author tianmaolin004
 * @date 2023/8/14
 */
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "sceneCode", visible = true)
@JsonSubTypes(value = {
        @JsonSubTypes.Type(value = JmBrandEnterSceneModel.class, name = "JmBrandEnterSceneModel"),
        @JsonSubTypes.Type(value = JmsEnterSceneModel.class, name = "JmsEnterSceneModel")
})
@Data
public class SceneModel {
    /**
     * 场景名称
     */
    private String sceneCode;
    /**
     * 场景时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private LocalDateTime sceneTime;
    /**
     * 请求数据来源
     */
    private String requestSource;
}

继承基类的类型一

package com.example.springboot.controller.model;
import lombok.*;
/**
 * @author tianmaolin004
 * @date 2023/8/14
 */
@Data
@EqualsAndHashCode(callSuper = true)
public class JmBrandEnterSceneModel extends SceneModel {
    /**
     * 加盟品牌名称
     */
    private String brandName;
    /**
     * 加盟品牌ID
     */
    private String brandId;
    /**
     * 加盟公司税号
     */
    private String comTaxNo;
}

继承基类的类型二

package com.example.springboot.controller.model;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.*;
import java.time.LocalDateTime;
/**
 * @author tianmaolin004
 * @date 2023/8/14
 */
@Data
@EqualsAndHashCode(callSuper = true)
public class JmsEnterSceneModel extends SceneModel {
    /**
     * 加盟商名称
     */
    private String franchiserName;
}

数据请求接口

请求接口

package com.example.springboot.controller;
import com.example.springboot.controller.model.SceneModel;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * @author tianmaolin004
 * @date 2023/8/14
 */
@RestController
@RequestMapping("/scene")
public class SceneSyncController {
    @PostMapping("/sync")
    public void sceneSync(@RequestBody SceneModel sceneModel) {
        System.out.println(sceneModel);
    }
}

请求实验示例

POSTMAN请求一

请求结果一

POSTMAN请求二

请求结果二

这样随着我请求的不同,Jackson依据不同请求Model中的属性进行解析判断。需要注意的是Jackson本身支持这一注解,并非只有SpringBoot支持,只不过SpringBoot的mvc请求使用了Jackson

JsonTypeInfo用法

这里简单普及一下,@JsonTypeInfo 是 Jackson 库中的注解之一,用于在序列化和反序列化 JSON 数据时处理多态性,特别是在处理继承结构时非常有用。它允许在 JSON 数据中包含有关对象类型的信息,以便正确地进行数据绑定。

以下是 @JsonTypeInfo 注解的主要参数和功能:

  • use:定义类型信息的使用方式。可以使用以下常量之一,以告诉 Jackson 库在序列化和反序列化时如何处理类型信息:
  • JsonTypeInfo.Id.CLASS:将类的全名作为类型信息。
  • JsonTypeInfo.Id.NAME:将一个字符串作为类型信息,需要与 @JsonSubTypes 注解一起使用,一般使用这个配置
  • JsonTypeInfo.Id.MINIMAL_CLASS:类似于 CLASS,但只使用类名的相对路径。
  • JsonTypeInfo.Id.NONE:不包含任何类型信息。
  • JsonTypeInfo.Id.CUSTOM:使用自定义的类型解析器处理类型信息。
  • include:定义类型信息的包含位置。可以是以下常量之一:
  • JsonTypeInfo.As.WRAPPER_OBJECT:将类型信息包装在 JSON 对象中。
  • JsonTypeInfo.As.PROPERTY:将类型信息作为 JSON 属性添加到数据中,一般使用这个配置
  • property:定义用于存储类型信息的属性名。默认为 "@class"。当 include 设置为 JsonTypeInfo.As.PROPERTY 时,此属性用于存储类型信息。
  • visible:设置类型信息是否可见。默认为 false,意味着类型信息不会序列化到 JSON 数据中。如果设置为 true,类型信息将包含在 JSON 数据中,一般使用这个配置设置为true
  • defaultImpl:定义默认的实现类,用于在反序列化时处理无法匹配类型信息的情况。
  • useDefaultImpl:设置是否在无法匹配类型信息时使用默认实现类。默认为 true

综上所述,@JsonTypeInfo 注解用于在序列化和反序列化 JSON 数据时处理多态性和继承结构,通过在数据中包含类型信息来确保正确的映射。

总结一下

JsonTypeInfo注解的使用可以降低同一类数据处理接口的提供数量,调用方可以只调用一个接口,接口内部可以依据调用方组装的Model和内置参数确定处理逻辑,扩展性和易用性都很强,在数据同步的场景里挺值得一用的。

相关文章
|
7月前
|
XML JSON 前端开发
前端网络请求真的搞懂了吗?解密前端参数传递方式,让开发更从容(二)
前端网络请求真的搞懂了吗?解密前端参数传递方式,让开发更从容
|
7月前
|
C++
C++ 数据封装的方法,重点是其编程思想
在C++中,数据封装一般指的是将数据和操作这些数据的函数绑定在一起的程序设计方式。通常使用C++的类来实现
65 7
|
7月前
|
XML 前端开发 JavaScript
前端网络请求真的搞懂了吗?解密前端参数传递方式,让开发更从容(一)
前端网络请求真的搞懂了吗?解密前端参数传递方式,让开发更从容
|
XML Java API
深入谈谈API接口的作用
深入谈谈API接口的作用
|
前端开发
前端学习笔记202306学习笔记第四十九天-构造器模式2
前端学习笔记202306学习笔记第四十九天-构造器模式2
44 0
|
前端开发
前端学习案例1-拷贝继承
前端学习案例1-拷贝继承
57 0
前端学习案例1-拷贝继承
|
前端开发
前端学习案例2-拷贝继承2
前端学习案例2-拷贝继承2
45 0
前端学习案例2-拷贝继承2
|
前端开发
前端学习案例18-对象封印
前端学习案例18-对象封印
42 0
前端学习案例18-对象封印
|
前端开发
前端学习案例2-对象的封印
前端学习案例2-对象的封印
40 0
前端学习案例2-对象的封印