前言
Jackson解析json字符串时,如果遇到解析不了的字段会报错,那我们可以通过如下配置来解决:
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
但是如果序列化Java实体对象时,也想要隐藏掉一些不需要的字段,该怎么做呢?
我们可以通过多种注解的方式对其进行隐藏,下面就介绍下这几种办法;
至于为啥需要隐藏字段,是因为有时候业务会有一些比较隐私的属性不想被人看到,比如密码字段等等;
目录
- 字段加注解
- 类加注解
- 类型加注解
- 过滤器
正文
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);
输出如下:
可以看到,密码属性没有打印出来,说明被成功隐藏了
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);
输出如下:
可以看到,密码属性没有打印出来,说明被成功隐藏了
这种注解的好处就是隐藏的字段一目了然,可视化效果较好;
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属性被忽略了;
这个方法用的比较少,只在有特定类型需要被隐藏时才会用到,比如自己定义的一个隐私类;
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属性被隐藏了

过滤器这种方式乍看会比较复杂,但真正用起来会比前面的几种更加灵活,因为待隐藏的参数可以通过多种方式进行配置,不需要写死;
而且可以将序列化和反序列化分开配置,比如上面的例子,就是配置的序列化时才会隐藏password属性:
SimpleBeanPropertyFilter filter = SimpleBeanPropertyFilter.serializeAllExcept("password");
总结
本篇主要介绍了Jackson隐藏属性的四种方式:
- 字段加注解,序列化和反序列化都会隐藏字段;
- 类加注解,序列化和反序列化都会隐藏字段,集中处理,可视化效果好;
- 类型加注解,序列化和反序列化都会隐藏字段,2.5+版本只支持数组类型和自定义类型,比较局限;
- 过滤器,可以分开配置序列化和反序列化的隐藏字段,而且参数配置比较灵活;
评论区