【问题标题】:Make @JsonView annotation on controller action include properties by default使控制器动作上的@JsonView 注解默认包含属性
【发布时间】:2014-11-28 12:30:50
【问题描述】:

当您使用 Jackson 的 writerWithView 时,任何没有 @JsonView 注释的属性仍会被序列化。然而,在 Spring MVC 操作上使用 @JsonView 似乎需要 @JsonView 出现在每个属性上。

如果说我们有以下模型:

public class User {
    private String username;
    private String emailAddress;

    public String getUsername() { return username; }
    @JsonView(DetailView.class)
    public String getEmailAddress() { return emailAddress; }
}

并且DetailView 扩展了BasicView,当我使用基本视图进行序列化时,我希望username 被序列化。这就是我们使用writerWithView时发生的情况:

@RequestMapping(value = "/me", method = GET)
@ResponseBody
public String getMe() throws JsonProcessingException {
    User user = getCurrentUser();
    return objectMapper.writerWithView(BasicView.class).writeValueAsString(user);

 }

但是,从 Spring MVC 4.1 开始,我们可以改为执行以下操作:

@RequestMapping(value = "/me", method = GET)
@ResponseBody
@JsonView(BasicView.class)
public User getMe() throws JsonProcessingException {
    return getCurrentUser();

 }

后者导致响应为{} 而不是{username:"David"}。如果我们将@JsonView(BasicView.class) 添加到getUsername() 上,这将按预期工作。

显然,我们可以使用前者或将@JsonView 添加到所有内容中,这两者都更冗长且容易出错。

这看起来有点像MapperFeature.DEFAULT_VIEW_INCLUSION 已被关闭,但显式启用它似乎并没有奏效。

有没有办法解决这个问题?

【问题讨论】:

    标签: json spring-mvc jackson


    【解决方案1】:

    MapperFeature.DEFAULT_VIEW_INCLUSION 被禁用确实是问题所在,但不幸的是 Spring 类并没有提供一种简单的方法来配置或替换默认消息转换器使用的 ObjectMapper。

    我发现解决此问题的最巧妙方法是扩展 DelegatingWebMvcConfiguration 并覆盖 configureMessageConverters 以填充默认转换器,然后覆盖有问题的 MappingJackson2HttpMessageConverter:

    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.http.converter.HttpMessageConverter;
    import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
    import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter;
    import org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration;
    import com.example.config.serialization.AllEncompassingFormHttpMessageConverterWithCustomObjectMapper;
    
    import java.util.List;
    
    
    @Configuration
    @ComponentScan({/*...*/})
    public class MyWebConfig extends DelegatingWebMvcConfiguration {
    
        @Bean
        public ObjectMapper objectMapper() {
            ObjectMapper objectMapper = new ObjectMapper();
            //...
            return objectMapper;
        }
    
        @Override
        public void configureMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
            super.configureMessageConverters(messageConverters);
            if (messageConverters.isEmpty()) {
                addDefaultHttpMessageConverters(messageConverters);
            }
    
            messageConverters.replaceAll(converter -> {
                if (converter instanceof MappingJackson2HttpMessageConverter) {
                    return new MappingJackson2HttpMessageConverter(objectMapper());
                } else if (converter instanceof AllEncompassingFormHttpMessageConverter) {
                    return new AllEncompassingFormHttpMessageConverterWithCustomObjectMapper(objectMapper());
                }
                return converter;
            });
        }
    
    }
    

    为了完整起见,您可能还想用您自己的副本替换上面的AllEncompassingFormHttpMessageConverter,该副本也允许指定ObjectMapper。我没有在此处包含 AllEncompassingFormHttpMessageConverterWithCustomObjectMapper 类 - 它是 AllEncompassingFormHttpMessageConverter 的一个简单副本,它将 ObjectMapper 构造函数参数转发到它创建的 MappingJackson2HttpMessageConverter。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-22
      • 2016-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-10
      • 2012-09-27
      • 2016-08-23
      相关资源
      最近更新 更多