当前位置:首页 > 技术分析 > 正文内容

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

ruisui883个月前 (02-04)技术分析14

前言

在我们前后端联调时,很经常以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 {

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


    @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();
    }

前端示例代码


浏览器访问结果


可以发现精度丢失了

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

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

示例

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

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

可以发现精度没有丢失了

场景三:数据脱敏

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

1、自定义脱敏序列化器

RequiredArgsConstructor
public class SensitiveJsonSerializer extends JsonSerializer 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-json-render

扫描二维码推送至手机访问。

版权声明:本文由ruisui88发布,如需转载请注明出处。

本文链接:http://www.ruisui88.com/post/1659.html

标签: objectmapper
分享给朋友:

“聊聊springboot项目中使用jackson的一些小技巧” 的相关文章

学无止境:Git 如何优雅地回退代码

来源:https://zhenbianshu.github.io前言从接触编程就开始使用 Git 进行代码管理,先是自己玩 Github,又在工作中使用 Gitlab,虽然使用时间挺长,可是也只进行一些常用操作,如推拉代码、提交、合并等,更复杂的操作没有使用过,看过的教程也逐渐淡忘了,有些对不起 L...

GitLab-合并请求

描述合并请求可用于在您对项目进行的其他人员之间交换代码,并轻松与他们讨论更改。合并请求的步骤步骤1-在创建新的合并请求之前,GitLab中应该有一个创建的分支。您可以参考本章来创建分支-步骤2-登录到您的GitLab帐户,然后转到“ 项目”部分下的项目 -步骤3-单击“ 合并请求”选项卡,然后单击“...

30 个纯 HTML5 实现的游戏

浏览器和 JavaScript 的功能逐年不断的变强变大。曾几何时,任何类型的游戏都需要Flash。但随着 HTML5 发展,HTML5 + WebGL 游戏式就慢慢占领着这个舞台。以下是30款流行的游戏,它们可以在所有现代浏览器中运行,并且只使用web技术构建。1. HexGL地址:http://...

摄影后期必看 | PS插件camera raw 16.4教程 | 范围蒙版

范围蒙版Camera Raw 【蒙版】模块中提供了三个范围蒙版工具,可以通过特定的范围来创建蒙版。此次新增的【范围蒙版】大大加强了acr插件对局部调整的能力。点击下拉小箭头可以看到【颜色范围】,可用于快速选择想要编辑的颜色。快捷键:Shift + C【明亮度范围】,可用于快速选择想要调整的明亮度。快...

Gemini应用在Android上广泛推出2.0闪电模式切换器

#头条精品计划# 快速导读谷歌(搜索)应用的测试频道在安卓设备的双子应用中推出了2.0闪电实验功能,现已向稳定用户开放。双子应用通过谷歌应用运行,目前推出的15.50版本中,用户可通过模型选择器体验不同选项,包括1.5专业版、1.5闪电版和2.0闪电实验版。2.0闪电实验模型提供了更快的响应速度和优...

最快清除数组空值?分享 1 段优质 JS 代码片段!

本内容首发于工粽号:程序员大澈,每日分享一段优质代码片段,欢迎关注和投稿!大家好,我是大澈!本文约 600+ 字,整篇阅读约需 1 分钟。今天分享一段优质 JS 代码片段,用最简洁的代码清除了数组中的空值。老规矩,先阅读代码片段并思考,再看代码解析再思考,最后评论区留下你的见解!const arr...