侧边栏壁纸
  • 累计撰写 94 篇文章
  • 累计创建 100 个标签
  • 累计收到 10 条评论

目 录CONTENT

文章目录

Jackson如何隐藏字段

汤圆学Java
2022-02-10 / 0 评论 / 0 点赞 / 318 阅读 / 4,059 字
温馨提示:
本文最后更新于 2022-02-10,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

前言

Jackson解析json字符串时,如果遇到解析不了的字段会报错,那我们可以通过如下配置来解决:

objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

但是如果序列化Java实体对象时,也想要隐藏掉一些不需要的字段,该怎么做呢?

我们可以通过多种注解的方式对其进行隐藏,下面就介绍下这几种办法;

至于为啥需要隐藏字段,是因为有时候业务会有一些比较隐私的属性不想被人看到,比如密码字段等等;

目录

  1. 字段加注解
  2. 类加注解
  3. 类型加注解
  4. 过滤器

正文

1. 字段加注解

注解:@JsonIgnore序列化和反序列化都会被隐藏

这个是最方便的,需要隐藏哪个字段,就直接在字段上加注解@JsonIgnore

还是以User实体为例:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {

    private String username;

    @JsonIgnore
    private String password;

}

如上所示,我们在password字段上加了@JsonIgnore注解,这样User实体在序列化时,就不会包含password字段;

下面我们简单测试一下:

User user = new User("admin", "123");
ObjectMapper objectMapper = new ObjectMapper();
String str = objectMapper.writeValueAsString(user);
System.out.println(str);

输出如下:

image-20220210175410865

可以看到,密码属性没有打印出来,说明被成功隐藏了

2. 类加注解

注解:@JsonIgnoreProperties序列化和反序列化都会被隐藏

字段加注解很方便,但是需要挨个给字段加注解;

如何想集中处理,那么我们可以直接在类上加注解,修改后的User实体类如下所示:

@Data
@AllArgsConstructor
@NoArgsConstructor
@JsonIgnoreProperties(value = {"password"})
public class User {

    private String username;

    private String password;

}

这里的value值是一个string[]数组,如果想隐藏多个字段,直接添加即可,比如value={"username", "password"}

下面我们简单测试一下:

User user = new User("admin", "123");
ObjectMapper objectMapper = new ObjectMapper();
String str = objectMapper.writeValueAsString(user);
System.out.println(str);

输出如下:

image-20220210175410865

可以看到,密码属性没有打印出来,说明被成功隐藏了

这种注解的好处就是隐藏的字段一目了然,可视化效果较好;

3. 类型加注解

注解:@JsonIgnoreType,序列化和反序列化都会隐藏

这种方法范围更广,它不是针对具体的实体类,而是针对字段的类型进行批量处理;

比如隐藏了String[]数组类型,那么所有String数组类型的字段都会被忽略;

从2.5版本开始,@JsonIgnoreType注解只适用于自定义类型和数组类型,基本类型不再适用(比如String类型就无效)

先给User类加一个String[]字段:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {

    private String username;

    public String password;
    
    public String[] nicknames;

}

再定义如下的一个类,并加了@JsonIgnoreType注解:这个类就是负责存储所有需要隐藏的类型

@JsonIgnoreType
public class MyIgnoreType {
}

但是我们不直接去修改这个类,而是通过动态的方式,为其添加属性,代码如下:objectMapper.addMixIn

User user = new User("admin", "123", new String[]{"jalon"});
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.addMixIn(String[].class, MyIgnoreType.class);
String str = objectMapper.writeValueAsString(user);
System.out.println(str);

此时输出如下:可以看到String[]类型的nicknames属性被忽略了;

image-20220210182804059

这个方法用的比较少,只在有特定类型需要被隐藏时才会用到,比如自己定义的一个隐私类;

4. 过滤器

这种方式跟第二种【类加注解】很相似,都是将需要隐藏的属性集中到一个地方进行处理;

不同的是第二种方式【类加注解】是直接在类上加注解,说明哪些属性需要隐藏,属于静态加载;

@JsonIgnoreProperties(value = {"password"})

而过滤器方式则是在运行时才确定哪些属性需要隐藏,属于动态加载;

下面就来演示下,用过滤器方式如何隐藏字段;

这里我们先在实体类上加一个注解@JsonFilter,表示这个实体类是通过过滤器的方式对属性进行隐藏:

@Data
@AllArgsConstructor
@NoArgsConstructor
@JsonFilter(value = "myFilter")
public class User {
    private String username;
    public String password;
}

具体隐藏哪些属性,在运行的时候进行动态配置:

User user = new User("admin", "123");
ObjectMapper objectMapper = new ObjectMapper();
// 配置过滤器,password就是需要隐藏的属性,这里可以添加多个
SimpleBeanPropertyFilter filter = SimpleBeanPropertyFilter.serializeAllExcept("password");
// 将配置好的过滤器 filter 应用到实体类上,这里的实体类就是 myFilter(通过@JsonFilter注解声明的)
SimpleFilterProvider filterProvider = new SimpleFilterProvider().addFilter("myFilter", filter);

String str = objectMapper.writer(filterProvider).writeValueAsString(user);
System.out.println(str);

运行输出如下:可以看到password属性被隐藏了

image-20220210215314850

过滤器这种方式乍看会比较复杂,但真正用起来会比前面的几种更加灵活,因为待隐藏的参数可以通过多种方式进行配置,不需要写死;

而且可以将序列化和反序列化分开配置,比如上面的例子,就是配置的序列化时才会隐藏password属性:

SimpleBeanPropertyFilter filter = SimpleBeanPropertyFilter.serializeAllExcept("password");

总结

本篇主要介绍了Jackson隐藏属性的四种方式:

  1. 字段加注解,序列化和反序列化都会隐藏字段;
  2. 类加注解,序列化和反序列化都会隐藏字段,集中处理,可视化效果好;
  3. 类型加注解,序列化和反序列化都会隐藏字段,2.5+版本只支持数组类型和自定义类型,比较局限;
  4. 过滤器,可以分开配置序列化和反序列化的隐藏字段,而且参数配置比较灵活;
0

评论区