绝了!Spring Boot凭@JsonView注解,强大到逆天

开发 前端
@JsonView 它是 Jackson 库中的一个强大注解。通过定义不同的视图类(通常为接口或类),并在实体类的字段上使用 @JsonView 注解标记该字段在哪个视图中可见,同时在控制器方法中通过 @JsonView 注解指定返回的视图,就可以灵活控制返回的字段内容,实现了根据不同场景动态选择序列化字段的目的,大大提高了代码的简洁性和可维护性。

环境:SpringBoot3.4.2

1. 简介

在基于 RESTful 架构的 Web 应用开发里,后端服务与前端客户端之间的数据交互通常采用 JSON 格式。然而,不同的业务场景对数据的需求存在差异。例如,在用户列表展示场景中,仅需返回用户的基本信息,如用户名、头像等;而在用户详情查看场景中,则需要返回用户的全部信息,包括敏感信息如密码等。

为满足这种多样化的数据需求,传统方式可能需要创建多个数据传输对象(DTO),分别对应不同的数据展示场景,但这会导致代码冗余和维护成本增加。

@JsonView 它是 Jackson 库中的一个强大注解。通过定义不同的视图类(通常为接口或类),并在实体类的字段上使用 @JsonView 注解标记该字段在哪个视图中可见,同时在控制器方法中通过 @JsonView 注解指定返回的视图,就可以灵活控制返回的字段内容,实现了根据不同场景动态选择序列化字段的目的,大大提高了代码的简洁性和可维护性。

2. 实战案例

2.1 基本使用

实体类定义

public class User {
  public interface PublicView {} ;
  public interface InternalView extends PublicView {} ;
  @JsonView(PublicView.class)
  private Long id ;
  @JsonView(PublicView.class)
  private String name ;
  @JsonView(PublicView.class)
  private String address ;
  @JsonView(InternalView.class)
  private String password ;
  @JsonView(InternalView.class)
  private String idCard ;
  @JsonView(PublicView.class)
  private String email ;
  // getters, setters
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.

Controller接口

@RestController
@RequestMapping("/users")
public class UserController {
  @JsonView(User.PublicView.class)
  @GetMapping("/query")
  public User query() {
    return new User(1L, "pack", "四川乌鲁木齐市", "123456", 
        "152528202504096514", "pack@qq.com");
  }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

访问接口输出如下:

图片图片

如果将接口上的@JsonView修改为InternalView输出如下:

图片图片

所有的字段都输出了。

注意,如果你有字段没有添加@JsonView注解,那么将不会被输出(默认情况)。

2.2 编程方式

如果你想以编程方式实现上述功能(而不是声明一个 @JsonView 注解),可以将返回值用 MappingJacksonValue 对象包裹起来,并利用它来指定序列化视图:

@GetMapping("/getUser")
public MappingJacksonValue getUser() {
  User user = new User(1L, "pack", "四川乌鲁木齐市", "123456", 
      "152528202504096514", "pack@qq.com") ;
  MappingJacksonValue value = new MappingJacksonValue(user);
  value.setSerializationView(User.PublicView.class);
  return value;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

访问该接口,输出结果:

图片图片

2.3 视图Json

对于依赖视图的控制器,只需将序列化视图类添加到model中即可,如下例所示:

@Controller
public class UserViewController {
  @GetMapping("/userview")
  public ModelAndView userView(Model model) {
    User user = new User(1L, "pack", "四川乌鲁木齐市", "123456", 
      "152528202504096514", "pack@qq.com") ;
    model.addAttribute("user", user) ;
    model.addAttribute(JsonView.class.getName(), User.PublicView.class) ;
    return new ModelAndView(new MappingJackson2JsonView()) ;
  }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

我们以JsonView的完整类名作为key添加到Model中,最后返回时定义MappingJacksonJsonView视图对象即可控制输出的字段。

访问上面接口输出:

图片图片

2.4 限制反序列化

当我们不希望某些字段被反序列化时,我们也可以通过该视图技术来限制,如下示例:

@PostMapping("/deserialize_json")
public User deserialize(@RequestBody String json) throws Exception {
  ObjectMapper mapper = new ObjectMapper() ;
  User user = mapper
    .readerWithView(User.PublicView.class)
    .forType(User.class)
    .readValue(json) ;
  return user ;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

请求测试如下:

图片图片

我们的接口并没有对password和idCard两个字段进行反序列化。

2.5 配置默认行为

通过上面的示例我们了解到,可以利用 @JsonView 注解来指定字段在哪些视图下可以被序列化输出。如果字段未添加 @JsonView 注解,则默认情况下该字段不会被输出。然而,当实体类的字段数量较多时,为每个字段单独添加注解会非常繁琐。为此,我们可以通过如下配置来更改这一默认行为:

spring:
  jackson:
    mapper:
      default-view-inclusion: true
  • 1.
  • 2.
  • 3.
  • 4.

接下来,我们将User修改如下:

public class User {
  private Long id ;
  private String name ;
  private String address ;
  @JsonView(InternalView.class)
  private String password ;
  @JsonView(InternalView.class)
  private String idCard ;
  private String email ;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

我们将公共字段上的注解去掉,接下来,我们再次访问上面的/users/query接口

图片图片

没有添加注解的字段也可以输出了(这属于默认字段)。

注:我们的接口上还是需要@JsonView(User.PublicView.class)注解。

责任编辑:武晓燕 来源: Springboot全家桶实战案例源码
相关推荐

2025-04-10 00:22:22

Spring@JsonView字段

2025-04-10 00:25:00

Spring@JsonView注解

2023-06-02 16:24:46

SpringBootSSM

2017-08-02 14:44:06

Spring Boot开发注解

2021-04-13 20:24:57

Spring Boot注解spring

2024-10-14 17:18:27

2024-11-27 09:58:41

Spring模块化管理方式

2020-03-31 15:03:56

Spring Boot代码Java

2023-04-17 23:49:09

开发代码Java

2020-11-02 07:00:29

Spring Boo注解自动化

2019-08-15 10:56:10

WebServletSpring mvc

2020-12-15 10:46:29

事件监听器Spring Boot

2020-09-21 06:54:59

热部署Spring日志

2024-11-06 11:33:09

2025-02-26 10:00:00

开发APIJava

2012-11-12 15:08:14

搜狗

2017-05-12 15:47:15

Spring BootMybatis Ann Web

2025-02-12 08:57:43

Spring动态注册组件

2024-11-01 10:40:32

2022-05-17 08:40:20

PythonWiFi密码代码
点赞
收藏

51CTO技术栈公众号