Jackson注解大全(下)
4.Jackson常用注解
4.1. @JsonProperty
@JsonProperty 注解用于属性上,作用是把该属性的名称序列化为另外一个名称,例如将theName属性序列化为name,使用@JsonProperty("name")
注解 。
@JsonProperty不仅仅是在序列化的时候有用,反序列化的时候也有用,比如有些接口返回的是json字符串,命名又不是标准的驼峰形式,在映射成对象的时候,在类的属性上加上@JsonProperty注解,里面写上返回的json串对应的名字即可。
定义实体类:
public class UserWithGetter {
private String name;
private int age;
@JsonProperty("name")
public void setTheName( String name) {
this.name = name;
}
@JsonProperty("name")
public String getTheName() {
return name;
}
//.....
}
测试并验证结果:
@Test
public void jsonProperty() throws IOException {
UserWithGetter user = new UserWithGetter("Jack", 25);
String result = new ObjectMapper().writeValueAsString(user);
System.out.println(result);
UserWithGetter resultUser= new ObjectMapper().readerFor(UserWithGetter.class)
.readValue(result);
System.out.println(resultUser);
}
测试结果:
{"age":25,"name":"Jack"}
UserWithGetter{name='Jack', age=25}
4.2. @JsonFormat
@JsonFormat注解指定序列化日期和时间的格式
使用@JsonFormat来控制属性birthday的格式:
public class PersonWithFormat {
private String name;
@JsonFormat(shape = JsonFormat.Shape.BINARY, pattern = "yyyy-MM-dd hh:mm:ss")
private Date birthday;
//.....
}
测试:
@Test
public void jsonFormat() throws JsonProcessingException, ParseException {
SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
df.setTimeZone(TimeZone.getTimeZone("UTC"));
String toParse = "20-05-2020 02:30:00";
Date date = df.parse(toParse);
PersonWithFormat event = new PersonWithFormat("Jack", date);
String result = new ObjectMapper().writeValueAsString(event);
System.out.println(result);
}
输出结果:
{
"name":"Jack",
"birthday":"2020-05-20 02:30:00"
}
4.3. @JsonUnwrapped
@JsonUnwrapped定义了在序列化/反序列化时,将嵌套的对象属性,序列化到JSON的同一级。
定义UnwrappedUser实体:
public class UnwrappedUser {
public int id;
@JsonUnwrapped
public Name name;
public static class Name {
public String firstName;
public String lastName;
public Name() {
}
public Name( String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
}
序列化过程:
@Test
public void jsonUnwrapped() throws JsonProcessingException {
UnwrappedUser.Name name = new UnwrappedUser.Name("John", "Doe");
UnwrappedUser user = new UnwrappedUser(1, name);
String result = new ObjectMapper().writeValueAsString(user);
System.out.println(result);
}
观察输出结果:嵌套类的字段与其他字段一起展开:
{"id":1,"firstName":"John","lastName":"Doe"}
4.4. @JsonView
@JsonView注解作用是将java对象序列化为JSON时,过滤敏感字段或者不需要字段,使用步骤如下:
首先,声明视图:
public class Views {
public static class UserInfo {
}
public static class UserDetailInfo extends UserInfo {
}
}
其次,定义序列化实体UserInfo:
public class UserInfo {
@JsonView(Views.UserInfo.class)
private String username;
@JsonView(Views.UserDetailInfo.class)
private String password;
@JsonView(Views.UserInfo.class)
private int age;
//.......
}
最后,测试:
@Test
public void jsonView() throws JsonProcessingException {
UserInfo item = new UserInfo("Tom", "123456", 27);
String result = new ObjectMapper().writerWithView(Views.UserInfo.class)
.writeValueAsString(item);
System.out.println(result);
result = new ObjectMapper().writerWithView(Views.UserDetailInfo.class)
.writeValueAsString(item);
System.out.println(result);
}
输出结果:
{"username":"Tom","age":27}
{"username":"Tom","password":"123456","age":27}
4.5.@ JsonManagedReference,@ JsonBackReference
这两个注解通常配对使用, 可以解决两个不同类的属性的父子关系和循环引用。
@JsonBackReference标注的属性在序列化时,会被忽略。而@JsonManagedReference标注的属性则会被序列化。在序列化时,@JsonBackReference的作用相当于@JsonIgnore,此时可以没有@JsonManagedReference。但在反序列化时,如果没有@JsonManagedReference,则不会自动注入@JsonBackReference标注的属性(被忽略的父或子);如果有@JsonManagedReference,则会自动注入自动注入@JsonBackReference标注的属性。
定义ItemWithRef实体
public class ItemWithRef {
public int id;
public String itemName;
@JsonManagedReference
public UserWithRef owner;
}
和UserWithRef实体
public class UserWithRef {
public int id;
public String name;
@JsonBackReference
public List<ItemWithRef> userItems;
}
测试:
@Test
public void jacksonReferenceAnnotation() throws JsonProcessingException {
UserWithRef user = new UserWithRef(1, "John");
ItemWithRef item = new ItemWithRef(2, "book", user);
user.addItem(item);
String result = new ObjectMapper().writeValueAsString(item);
System.out.println(result);
}
输出结果:
{"id":2,"itemName":"book","owner":{"id":1,"name":"John"}}
4.6.@JsonIdentityInfo
@JsonIdentityInfo注解,作用于类或属性上,被用来在序列化/反序列化时为该对象或字段添加一个对象识别码,通常是用来解决循环嵌套的问题。定义两个实体,ItemWithIdentity实体
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public class ItemWithIdentity {
public int id;
public String itemName;
public UserWithIdentity owner;
}
和UserWithIdentity实体:
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public class UserWithIdentity {
public int id;
public String name;
public List<ItemWithIdentity> userItems;
}
测试:
@Test
public void jsonIdentityInfo() throws JsonProcessingException {
UserWithIdentity user = new UserWithIdentity(1, "John");
ItemWithIdentity item = new ItemWithIdentity(2, "book", user);
user.addItem(item);
String result = new ObjectMapper().writeValueAsString(item);
System.out.println(result);
}
输出结果:
{"id":2,"itemName":"book","owner":{"id":1,"name":"John","userItems":[2]}}
4.7. @JsonFilter
@JsonFilter注解的作用是在序列化的过程中过滤掉指定的属性,类似于@JsonIgnore注解。但是当有一堆字段需要配置,而且整个项目都需要统一处理的时候,@JsonFilter比较适合。
定义实体,然后指向过滤器:
@JsonFilter("myFilter")
public class UserWithFilter {
private int id;
private String name;
// ......
}
测试代码:
@Test
public void jsonFilter() throws JsonProcessingException {
UserWithFilter bean = new UserWithFilter(1, "Jack");
//此过滤器的含义是除name属性外, 其他属性都被过滤掉(不序列化)
FilterProvider filters = new SimpleFilterProvider().addFilter("myFilter", SimpleBeanPropertyFilter.filterOutAllExcept("name"));
String result = new ObjectMapper().writer(filters)
.writeValueAsString(bean);
System.out.println(result);
}
输出结果:
{"name":"Jack"}
5.自定义Jackson注解
使用@JacksonAnnotationsInside
创建自定义的Jackson注解 。
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonInclude(Include.NON_NULL)
@JsonPropertyOrder({ "name", "age","id" })
public @interface CustomAnnotation {
}
定义实体并使用新注解 :
@CustomAnnotation
public class UserCustomAnnotation {
private int id;
private String name;
private int age;
//省略 constructor getters setters
}
测试自定义注解 :
@Test //测试自定义注解
public void customAnnotation() throws JsonProcessingException {
UserCustomAnnotation bean = new UserCustomAnnotation(1, "Jack", 28);
String result = new ObjectMapper().writeValueAsString(bean);
System.out.println(result);
}
序列化输出:
//添加注解 前
{"id":1,"name":"Jack","age":28}
//添加注解 后
{"name":"Jack","age":28,"id":1}
6.Jackson MixIn注解
Jackson MixIn注解用来忽略某个类型的所有字段。
首先,我们为要忽略的类型定义一个MixIn,并使用@JsonIgnoreType进行注解 。
@JsonIgnoreType
public class MixInForIgnoreType {
}
然后,注册该mixin来忽略此类型:
mapper.addMixIn(Employee.class, MixInForIgnoreType.class);
定义Company实体,忽略Employee类型的属性:
public class Company {
private int id;
private String companyName;
private Employee employee;
//省略 constructor getters setters
}
测试并验证结果:
@Test
public void mixInAnnotation() throws JsonProcessingException {
Company company = new Company(1, "小米", null);
String result = new ObjectMapper().writeValueAsString(company);
System.out.println(result);
ObjectMapper mapper = new ObjectMapper();
mapper.addMixIn(Employee.class, MixInForIgnoreType.class);
result = mapper.writeValueAsString(company);
System.out.println(result);
}
输出结果:
{"id":1,"companyName":"小米","employee":null}
{"id":1,"companyName":"小米"}
7.禁用Jackson注解
如何禁用所有Jackson注解?我们可以通过设置MapperFeature.USE_ANNOTATIONS
来禁用实体类上的Jackson注解,创建如下实体类:
@JsonInclude(Include.NON_NULL)
public class IncludeUser {
private int id;
private String name;
private int age;
private String address;
//省略 constructor getters setters
}
测试并验证结果:
@Test
public void disablingAllAnnotations() throws JsonProcessingException {
IncludeUser bean = new IncludeUser();
ObjectMapper mapper = new ObjectMapper();
mapper.disable(MapperFeature.USE_ANNOTATIONS);
String result = mapper.writeValueAsString(bean);
System.out.println(result);
}
禁用注解 之前输出结果:
{"id":0,"age":0}
禁用注解 之后输出结果:
{"id":0,"name":null,"age":0,"address":null}