Jackson注解大全(下)

发布时间 2023-12-28 10:41:46作者: 全琪俊

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}