You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SpringBoot中Jackson的@JsonView注解选择性序列化POJO配置问题

解决方案:SpringBoot 2.7.17 中实现@JsonView的局部生效

完全可行,核心思路是不对全局ObjectMapper做修改,只为新控制器单独配置开启MapperFeature.DEFAULT_VIEW_INCLUSION = false的序列化规则,具体实现步骤如下:

1. 创建自定义ObjectMapper

创建一个仅用于新控制器的ObjectMapper实例,开启DEFAULT_VIEW_INCLUSION为false:

@Configuration
public class CustomJsonViewConfig {

    @Bean(name = "jsonViewObjectMapper")
    public ObjectMapper jsonViewObjectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        // 开启该配置后,仅序列化带指定@JsonView的字段
        mapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false);
        return mapper;
    }
}

2. 为新控制器配置专属的消息转换器

通过@ControllerAdvice指定作用范围(比如新控制器所在的包或自定义注解),替换该范围内控制器的消息转换器为使用上述自定义ObjectMapper:

@ControllerAdvice(basePackages = "com.yourproject.newcontrollers") // 新控制器所在包
public class NewControllerJsonViewAdvice extends AbstractJsonResponseBodyAdvice {

    private final ObjectMapper jsonViewObjectMapper;

    public NewControllerJsonViewAdvice(@Qualifier("jsonViewObjectMapper") ObjectMapper jsonViewObjectMapper) {
        this.jsonViewObjectMapper = jsonViewObjectMapper;
    }

    @Override
    protected void beforeBodyWriteInternal(MappingJacksonValue bodyContainer, MediaType contentType, MethodParameter returnType, ServerHttpRequest request, ServerHttpResponse response) {
        bodyContainer.setMapper(jsonViewObjectMapper);
    }
}

3. 新控制器中使用@JsonView

在新控制器的接口方法上标注@JsonView指定视图,对应的POJO字段添加相同视图注解:

// 定义视图接口
public class Views {
    public static class Public {}
    public static class Internal extends Public {}
}

// POJO示例(老POJO无需修改,新POJO按需添加@JsonView)
public class User {
    private Long id; // 默认序列化(老控制器和未指定视图的新控制器接口都会返回)
    private String username; // 默认序列化
    @JsonView(Views.Internal.class)
    private String email; // 仅在新控制器指定Views.Internal视图时返回
}

// 新控制器示例
@RestController
@RequestMapping("/new-api/users")
public class NewUserController {

    @GetMapping("/{id}")
    @JsonView(Views.Public.class)
    public User getUserPublicInfo(@PathVariable Long id) {
        // 返回的User对象仅序列化未标注@JsonView或标注Views.Public的字段
        return userService.getUserById(id);
    }

    @GetMapping("/{id}/internal")
    @JsonView(Views.Internal.class)
    public User getUserInternalInfo(@PathVariable Long id) {
        // 返回的User对象会序列化标注Views.Internal或其父视图的字段
        return userService.getUserById(id);
    }

    @GetMapping("/{id}/all")
    public User getUserAllInfo(@PathVariable Long id) {
        // 未标注@JsonView,新控制器会用自定义ObjectMapper,但因为没指定视图,会序列化所有字段(包括未加@JsonView的)
        return userService.getUserById(id);
    }
}

4. 老代码不受影响

老控制器和未添加@JsonView的新控制器接口,依然保持默认行为:序列化POJO的所有字段,无需修改任何老POJO或控制器。


内容的提问来源于stack exchange,提问作者Shvalb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 20:05:06