用于 API 不同部分的多个 ObjectMapper

Mic*_*dis 3 java spring spring-mvc jackson

目前我@Bean的 Spring Boot 应用程序中有这样的配置:

@Bean
public ObjectMapper objectMapper() {
    ObjectMapper mapper = new ObjectMapper();
    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    mapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, true);
    mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);

    mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE);
    mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
    mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);

    return mapper;
}
Run Code Online (Sandbox Code Playgroud)

是否可以为 API 的不同部分使用不同的 ObjectMappers?例如,我感兴趣的是针对 API 的不同部分采用不同的属性命名策略。我希望我的 API 的一部分(例如/api/v1/snake/**)能够使用SNAKE_CASE,并且它的一部分(例如/api/v1/camel/**)能够与LOWER_CAMEL_CASE.

谢谢!

Jea*_*ond 9

如果 的两个部分API不处理相同的域对象,您将能够通过提供您自己的MappingJackson2HttpMessageConverter覆盖canReadcanWrite方法的实现来做到这一点。这是一个使用必须序列化的对象的基础包的示例:

自定义转换器:

public class CustomConverter extends MappingJackson2HttpMessageConverter {

    private String basePackage;

    public CustomConverter(String basePackage) {
        this.basePackage = basePackage;
    }

    @Override
    public boolean canRead(Type type, Class<?> contextClass, MediaType mediaType) {
        if (contextClass.getName().startsWith(basePackage)) {
            return super.canRead(type, contextClass, mediaType);
        }
        return false;
    }

    @Override
    public boolean canWrite(Class<?> clazz, MediaType mediaType) {
        if (clazz.getName().startsWith(basePackage)) {
            return super.canWrite(clazz, mediaType);
        }
        return false;
    }
}
Run Code Online (Sandbox Code Playgroud)

配置

@Configuration
public class Configuration {

    @Bean
    public MappingJackson2HttpMessageConverter camelCaseConverter() {
        MappingJackson2HttpMessageConverter converter = new CustomConverter("package.camel");
        converter.setObjectMapper(camelCaseObjectMapper());
        return converter;
    }

    @Bean
    public MappingJackson2HttpMessageConverter snakeCaseConverter() {
        MappingJackson2HttpMessageConverter converter = new CustomConverter("package.snake");
        converter.setObjectMapper(snakeCaseObjectMapper());
        return converter;
    }

    @Bean
    public ObjectMapper camelCaseObjectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, true);
        mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);

        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE);
        mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
        mapper.setPropertyNamingStrategy(PropertyNamingStrategy.LOWER_CAMEL_CASE);

        return mapper;
    }

    @Bean
    public ObjectMapper snakeCaseObjectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, true);
        mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);

        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE);
        mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
        mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);

        return mapper;
    }
}
Run Code Online (Sandbox Code Playgroud)