默认情况下,在控制器操作包括属性上创建@JsonView注释

时间:2014-11-28 12:30:51

标签: json spring-mvc 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已被关闭,但明确启用它似乎没有效果。

无论如何都要绕过这个?

1 个答案:

答案 0 :(得分:0)

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