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

news/2024/11/19 10:30:27/文章来源:https://www.cnblogs.com/linyb-geek/p/18280453

前言

在我们前后端联调时,很经常以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注解,来控制枚举序列化结果

    @JsonValuepublic Integer getCode() {return code;}

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

1

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

NORMAL

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

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

public class StatusEnumsJsonSerializer extends JsonSerializer<StatusEnums> {@Overridepublic void serialize(StatusEnums value, JsonGenerator gen, SerializerProvider serializers) throws IOException {gen.writeString(value.getCode().toString());}
}
public class StatusEnumsJsonDerializer extends JsonDeserializer<StatusEnums> {@Overridepublic 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")@ResponseBodypublic 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;}@Overridepublic void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {gen.writeString(DesensitizedUtil.desensitized(value,desensitizedType));}@Overridepublic 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@ConditionalOnMissingBeanpublic 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/836681.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

存储快照原理

快照有COW(Copy On Write,写时复制)和ROW(Redirect On Write,写重定向)两种实现方式。 1 .COW COW(Copy-On-Write),写时拷贝,也称为写前拷贝。 创建快照,如果源卷的数据发生了变化,快照系统会将原始数据拷贝到快照卷上的数据块中,然后再对源卷进行改写; OW快照在初…

树分治全家桶

树分治全家桶 树,(是一种益于保护环境植物)是图论当中的一种特殊图,由于(绿化环境的作用非常优秀)特殊性质丰富,经常出现在我们身边。 本文将主要介绍(如何植树)一种树上优美的暴力——树分治。 树分治 树分治可以将部分暴力降至 \(O(\log n)\) 至 \(O(\log^2 n)\) 级…

模拟计算hash前面N个0需要的时间

写了一个python代码用来模拟计算当hash前面有N个0时需要多长时间。 代码如下: import hashlib import time from datetime import timedelta from plyer import notificationdef find_hash_with_prefix_zeros(prefix_length=6):# 初始字符串base_text = "Hello, World!&q…

StopWatch使用

调试查看耗时的一个便捷类,一般只使用三个方法StopWatch stopWatch = new StopWatch();stopWatch.start("获取对象");//逻辑代码xxxxxxxxxxxstopWatch.stop();log.info(stopWatch.prettyPrint()); //打印详细信息

IDEA svn项目 更换SVN地址

原svn项目地址URL1,后来把项目移到了URL2,但自己的SVN地址是URL1且已改了好多东西,不想down URL2源码再改。 解决方法: 原文链接:https://blog.csdn.net/weixin_35721320/article/details/79290369

值得推荐的IT公司名单(广州篇)

广州,作为中国南方的重要城市,不仅历史悠久,而且在科技创新方面也具有极高的活力。特别是在IT领域,广州孕育了许多知名企业和创业公司,成为众多技术人才的聚集地。本文将介绍一些在广州值得去的IT公司,为那些希望在广州发展的技术人才提供参考。 互联网大厂 1、腾讯:作为…

项目经理必备:如何通过管理工具提高执行效率?

在瞬息万变的商业环境中,项目经理如同掌舵人,引领团队穿越风浪,确保项目按时、按质、按预算完成。然而,面对日益复杂的项目需求和不断变化的市场环境,仅凭传统的管理方式已难以满足高效执行的需求。此时,借助先进的项目管理工具,成为了项目经理提升执行效率、实现项目成…

PAM限制实测

计算节点pam限制调度系统slurm提供了pam插件,可以实现如下功能: 当且仅当计算节点运行普通用户作业的情况下,该用户才可以通过ssh登录该计算节点。 计算节点的调度系统安装后,在/lib64/security下存在如下三个库文件: /lib64/security/pam_slurm_adopt.a /lib64/security/…

linux学习day02_常用命令学习

1、那个 ~ 符号代表的是“使用者的主文件夹”的意思,他是个“变量!”举例来说,root的主文件夹在/root, 所以 ~ 就代表/root的意思 至于提示字符方面,在Linux当中,默认root的提示字符为 # ,而一般身份使用者的提示字符 为 $ .在 Linux 系统中,英文大小写字母是不一样的。…

赋能业务,驱动未来,科华数据召开CRM平台升级项目启动会

11月13日,全球卓越的智慧电能解决方案提供商-科华数据股份有限公司(以下简称“科华数据”)CRM平台升级项目启动会在厦门顺利举行。科华集团总裁陈四雄、科华数能总裁崔剑、科华数通副总裁林清民、纷享销客高级副总裁江水、中南战区交付总经理徐延涛、深圳分公司总经理杨小会…

使用Pytorch构建视觉语言模型(VLM)

视觉语言模型(Vision Language Model,VLM)正在改变计算机对视觉和文本信息的理解与交互方式。本文将介绍 VLM 的核心组件和实现细节,可以让你全面掌握这项前沿技术。我们的目标是理解并实现能够通过指令微调来执行有用任务的视觉语言模型。 总体架构VLM 的总体架构包括:图…