首页 > 其他分享 >聊聊springboot项目中使用jackson的一些小技巧

聊聊springboot项目中使用jackson的一些小技巧

时间:2024-11-19 10:17:54浏览次数:1  
标签:jackson springboot StatusEnums public 枚举 聊聊 序列化 class 脱敏

前言

在我们前后端联调时,很经常以json作为数据的交互格式,今天我们就来聊聊在开发springboot项目中,使用jackson进行数据渲染一些小技巧

场景一:枚举-JSON互转

在日常开发中我们为了避免过多的魔法值,使用枚举类来封装一些静态的状态代码。
但是在将这些枚举的意思正确而全面的返回给前端却并不是那么顺利,比如有个状态枚举类

public enum StatusEnums {

    NORMAL(1,"正常"),

    LOCK(2,"锁定"),

    DELETE(3,"删除");

    private Integer code;

    private String desc;

    StatusEnums(Integer code, String desc) {
        this.code = code;
        this.desc = desc;
    }


    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }



}

如果我们直接使用Jackson对枚举进行序列化,将只能简单的输出枚举的String名称

new ObjectMapper().writeValueAsString(StatusEnums.NORMAL);

输出结果为枚举名称:

NORMAL

而我们希望将枚举转为JSON对象,像下面这样:

{"code":200,"desc":"正常"}

那如何达到以上效果

方法一:使用@JsonValue 注解

我们通过@JsonValue注解,来控制枚举序列化结果

    @JsonValue
    public Integer getCode() {
        return code;
    }

比如StatusEnums.NORMAL最后最终序列化的值:

1

同样我们也可以通过@JsonValue注解进行反序列化,最终1反序列化的值为

NORMAL

方法二:通过自定义序列化/反序列器

a、 自定义序列化器以及反序列化器

public class StatusEnumsJsonSerializer extends JsonSerializer<StatusEnums> {

    @Override
    public void serialize(StatusEnums value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeString(value.getCode().toString());
    }
}
public class StatusEnumsJsonDerializer extends JsonDeserializer<StatusEnums> {


    @Override
    public StatusEnums deserialize(JsonParser p, DeserializationContext ctx) throws IOException, JsonProcessingException {
         if(p.getText() != null){
             return StatusEnums.getByCode(Integer.valueOf(p.getText()));
         }
        return null;
    }
}

b、在枚举类上加上自定义序列化、反序列化注解

 @JsonSerialize(using = StatusEnumsJsonSerializer.class)
 @JsonDeserialize(using =  StatusEnumsJsonDerializer.class)
    private StatusEnums status;

除了以上方法,还可以通过@JsonCreator来达到上述效果,因为demo没实现,这边就不演示了

场景二:规避前端JavaScript接收后端Long属性值,精度丢失问题

示例演示

后端示例代码

  @GetMapping("get")
    @ResponseBody
    public User getUser(){
       return User.builder().name("张三")
                .password("123456")
                .status(StatusEnums.NORMAL)
                .id(987654321123456789L).build();
    }

前端示例代码

<button id="loadDataButton">Load Data</button>
<div id="dataDisplay"></div>

<script>
    $(document).ready(function() {
    $("#loadDataButton").click(function() {
        $.ajax({
            url: "/user/get",
            type: "GET",
            data: {},
            success: function(response) {
                $("#dataDisplay").html("id: " + response.id + "<br/>name: " + response.name + "<br/>password:  " + response.password + "<br/>status:  " + response.status);
            },
            error: function(xhr, status, error) {
                console.error("Error: " + error);
            }
        });
    });
});
</script>

浏览器访问结果


可以发现精度丢失了

方法一:通过@JsonSerialize注解,将long序列化为字符串

注: 直接通过jackson自带的序列化器

示例

@JsonSerialize(using = ToStringSerializer.class)
    private Long id;

加上该注解后,通过浏览器查看效果

可以发现精度没有丢失了

场景三:数据脱敏

敏感数据脱敏展示,应该是挺通用需求,我们可以通过自定义序列化器实现这一效果

1、自定义脱敏序列化器

RequiredArgsConstructor
public class SensitiveJsonSerializer extends JsonSerializer<String> implements ContextualSerializer {

    private final DesensitizedUtil.DesensitizedType desensitizedType;

    public SensitiveJsonSerializer(){
        this.desensitizedType = DesensitizedUtil.DesensitizedType.CLEAR_TO_EMPTY;
    }



    @Override
    public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
            gen.writeString(DesensitizedUtil.desensitized(value,desensitizedType));
    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
        Sensitive sensitive = property.getAnnotation(Sensitive.class);
        if (sensitive != null){
            return new SensitiveJsonSerializer(sensitive.type());
        }

        return prov.findValueSerializer(property.getType(), property);
    }
}

2、自定义脱敏注解

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@JacksonAnnotationsInside
@JsonSerialize(using = SensitiveJsonSerializer.class)
public @interface Sensitive {

    DesensitizedUtil.DesensitizedType type();
}

3、在需要脱敏的字段上,加上脱敏注解

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class User {

    @JsonSerialize(using = ToStringSerializer.class)
    private Long id;

    @Sensitive(type = DesensitizedUtil.DesensitizedType.CHINESE_NAME)
    private String name;

    @Sensitive(type = DesensitizedUtil.DesensitizedType.PASSWORD)
    private String password;
    }

a、 未加脱敏注解时,通过浏览器访问

发现没有脱敏,现在我们针对名字和密码进行脱敏

b、 名字和密码加上脱敏注解

    @Sensitive(type = DesensitizedUtil.DesensitizedType.CHINESE_NAME)
    private String name;

    @Sensitive(type = DesensitizedUtil.DesensitizedType.PASSWORD)
    private String password;

观察浏览器

总结

本文介绍枚举和json转换、long精度问题、数据脱敏三种我们日常开发比较常用的场景,但不知道大家发现没,这三种场景本质上都是通过json的序列化和反序列化实现,因此我们可以通过定制全局json序列化、反序列化器来实现。核心代码如下

    @Bean
    @ConditionalOnMissingBean
    public Jackson2ObjectMapperBuilderCustomizer customJackson2ObjectMapperBuilderCustomizer(){
        return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder
                .serializerByType(Long.class,ToStringSerializer.instance)
                .serializerByType(StatusEnums.class,new StatusEnumsJsonSerializer())
                .deserializerByType(StatusEnums.class,new StatusEnumsJsonDerializer());

    }

demo链接

https://github.com/lyb-geek/springboot-learning/tree/master/springboot-config-refresh

标签:jackson,springboot,StatusEnums,public,枚举,聊聊,序列化,class,脱敏
From: https://www.cnblogs.com/linyb-geek/p/18280453

相关文章

  • 【开题报告】基于Springboot+vue乡村信息化管理系统(程序+源码+论文) 计算机毕业设计
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着信息技术的迅猛发展,信息化已成为推动社会进步和经济发展的重要力量。在乡村地区,传统的管理方式逐渐暴露出效率低下、信息不透明等问题,严重制约了......
  • 基于Springboot社区闲置物品交换置换系统网站设计与实现(作品+论文+开题报告)
      博主介绍:黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;专注大学生毕业设计教育、辅导。所有项目都配有从入门到精通的基础知识视频课程,学习后应对毕业设计答辩,提供核心代码讲解,答辩指导。项目配有对应开......
  • (分享源码)计算机毕业设计必看必学 上万套实战教程手把手教学JAVA、PHP,node.js,C++、pyth
     摘 要随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,校园跳蚤市场管理系统被用户普遍使用,为方便用户能够可以随时进行校园跳蚤市场管理系统的数据信息管理,特开发了基于spri......
  • springboot跨域处理
    注册跨域过滤器 CorsFilter@BeanpublicCorsFiltercorsFilter(){CorsConfigurationconfig=newCorsConfiguration();config.addAllowedHeader("*");config.addAllowedMethod("*");config.addAllowedOriginPatte......
  • springboot美容院管理系统(代码+数据库+LW)
    摘  要如今的信息时代,对信息的共享性,信息的流通性有着较高要求,因此传统管理方式就不适合。为了让美容院信息的管理模式进行升级,也为了更好的维护美容院信息,美容院管理系统的开发运用就显得很有必要。并且通过开发美容院管理系统,不仅可以让所学的SpringBoot框架得到实际运用......
  • 基于springboot的“衣依”服装销售平台的设计与实现(代码+数据库+LW)
    摘要随着信息互联网购物的飞速发展,一般企业都去创建属于自己的电商平台以及购物管理系统。本文介绍了“衣依”服装销售平台的开发全过程。通过分析企业对于“衣依”服装销售平台的需求,创建了一个计算机管理“衣依”服装销售平台的方案。文章介绍了“衣依”服装销售平台的系统......
  • springboot扩展配置文件自动加载
    importcn.hutool.core.collection.ListUtil;importcn.hutool.core.convert.Convert;importcn.hutool.core.io.FileUtil;importcn.hutool.core.text.CharSequenceUtil;importcn.hutool.setting.yaml.YamlUtil;importlombok.extern.slf4j.Slf4j;importorg.springfr......
  • 聊聊你所知道的node中间层
    Node.js中间层(或称中间件层)是一个常见的架构模式,通常用于连接前端和后端,使得系统更具灵活性和可维护性。在这种模式中,Node.js作为一个中间层服务器,位于前端应用和后端服务之间,承担以下几项重要任务:1.数据处理与格式转换Node中间层可以接收前端的请求,在请求被转发给后端服......
  • springboot毕设个人博客网站程序+论文
    系统程序文件列表开题报告内容研究背景随着互联网的快速发展,个人博客作为一种表达自我、分享知识与见解的重要平台,受到了越来越多人的青睐。从早期的博客园、CSDN博客,到如今的各类自媒体平台,博客形式灵活多样,内容丰富多彩,成为连接作者与读者之间的桥梁。然而,市面上的博客平......
  • springboot毕设个人博客的设计与实现程序+论文
    系统程序文件列表开题报告内容研究背景随着互联网技术的飞速发展和普及,个人博客作为一种表达自我、分享知识和交流思想的平台,逐渐成为了现代人日常生活中不可或缺的一部分。特别是在当前信息爆炸的时代,人们渴望有一个属于自己的空间,用以记录生活点滴、展示专业技能、分享心......