📜  Jackson注释-@JsonView(1)

📅  最后修改于: 2023-12-03 14:42:11.934000             🧑  作者: Mango

Jackson注释-@JsonView

在使用Jackson序列化对象时,我们经常需要控制Json输出的内容。一个常见的需求是根据不同的场景,控制Json的输出内容。例如,根据不同的用户角色,输出不同的字段;根据不同的服务端端点,输出不同的数据。Jackson提供了一个注解@JsonView来满足这种需求。

基本用法

@JsonView注解用于定义view class(视图类),可以理解为不同的视图类对应不同的输出内容。在Java类中,我们可以为属性或者方法添加@JsonView注解,指定该属性/方法所对应的视图类。

@Getter
@Setter
public class User {
    @JsonView(View.Summary.class)
    private Long id;
    
    @JsonView(View.Summary.class)
    private String username;

    @JsonView(View.Detail.class)
    private String email;
    
    public interface View {
        interface Summary {}
        interface Detail extends Summary {}
    }
}

在上面的例子中,我们定义了一个User类,并通过View接口定义了两个视图类:Summary和Detail。其中,Summary视图类包括id和username两个属性;Detail视图类包括Summary视图类中的所有属性以及email属性。

接下来,我们可以使用ObjectMapper中的writerWithView方法来指定要序列化的视图类。

ObjectMapper mapper = new ObjectMapper();

User user = new User();
user.setId(1L);
user.setUsername("user1");
user.setEmail("user1@example.com");

String json1 = mapper
        .writerWithView(User.View.Summary.class)
        .writeValueAsString(user);
// {"id":1,"username":"user1"}

String json2 = mapper
        .writerWithView(User.View.Detail.class)
        .writeValueAsString(user);
// {"id":1,"username":"user1","email":"user1@example.com"}

在上面的代码中,我们分别使用了Summary和Detail两个视图类来序列化User对象。对于Summary视图类,只输出了id和username两个属性;对于Detail视图类,输出了Summary视图类中的所有属性以及email属性。

嵌套使用

除了为属性或者方法添加@JsonView注解外,我们还可以为视图类添加@JsonView注解,定义视图类之间的嵌套关系。

@Getter
@Setter
public class User {
    @JsonView(View.Summary.class)
    private Long id;
    
    @JsonView(View.Summary.class)
    private String username;

    @JsonView(View.Detail.class)
    private String email;
    
    @JsonView(View.Detail.class)
    private List<Role> roles;

    public interface View {
        interface Summary {}
        interface Detail extends Summary {}
        interface RoleDetail {}
    }
}

@Getter
@Setter
public class Role {
    @JsonView(User.View.RoleDetail.class)
    private Long id;
    
    @JsonView(User.View.RoleDetail.class)
    private String name;
}

在上面的例子中,我们为User类和Role类分别定义了视图类,并设置了它们之间的嵌套关系。具体来说,Detail视图类包括RoleDetail视图类,表示在输出Detail视图类时,同时输出RoleDetail视图类。

接下来,我们可以使用ObjectMapper中的writerWithView方法,输出包含嵌套视图的Json字符串。

ObjectMapper mapper = new ObjectMapper();

User user = new User();
user.setId(1L);
user.setUsername("user1");
user.setEmail("user1@example.com");

Role role1 = new Role();
role1.setId(1L);
role1.setName("role1");

Role role2 = new Role();
role2.setId(2L);
role2.setName("role2");

user.setRoles(Arrays.asList(role1, role2));

String json = mapper
        .writerWithView(User.View.Detail.class)
        .writeValueAsString(user);
// {"id":1,"username":"user1","email":"user1@example.com",
//  "roles":[{"id":1,"name":"role1"},{"id":2,"name":"role2"}]}

在上面的代码中,我们输出了包含嵌套视图的Json字符串。具体来说,我们使用Detail视图类输出了User对象,并在输出Roles属性时,同时使用RoleDetail视图类输出角色对象的id和name属性。

Conclusion

@JsonView注解是一个很方便的 Jackson 特性,可以帮助我们快速地控制 Json 输出的内容。当然,需要注意的是:每个视图类必须定义为接口类型,并且每个视图类之间必须存在继承关系或嵌套关系。