在使用RestTemplate时,我们如何配置内部Jackson映射器?

Usm*_*ail 69 spring jackson

我想更新Spring RestTemplate使用的jackson映射器的SerializationConfig.Feature ...属性,任何想法我怎么能到达它或我可以/应该配置它.

Tom*_*icz 90

默认RestTemplate构造函数注册一组HttpMessageConverters:

this.messageConverters.add(new ByteArrayHttpMessageConverter());
this.messageConverters.add(new StringHttpMessageConverter());
this.messageConverters.add(new ResourceHttpMessageConverter());
this.messageConverters.add(new SourceHttpMessageConverter());
this.messageConverters.add(new XmlAwareFormHttpMessageConverter());
if (jaxb2Present) {
    this.messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
}
if (jacksonPresent) {
    this.messageConverters.add(new MappingJacksonHttpMessageConverter());
}
if (romePresent) {
    this.messageConverters.add(new AtomFeedHttpMessageConverter());
    this.messageConverters.add(new RssChannelHttpMessageConverter());
}
Run Code Online (Sandbox Code Playgroud)

MappingJacksonHttpMessageConverter轮流,造成ObjectMapper直接实例.您可以找到此转换器并ObjectMapper在其之前替换或注册新转换器.这应该工作:

@Bean
public RestOperations restOperations() {
    RestTemplate rest = new RestTemplate();
    //this is crucial!
    rest.getMessageConverters().add(0, mappingJacksonHttpMessageConverter());
    return rest;
}

@Bean
public MappingJacksonHttpMessageConverter mappingJacksonHttpMessageConverter() {
    MappingJacksonHttpMessageConverter converter = new MappingJacksonHttpMessageConverter();
    converter.setObjectMapper(myObjectMapper());
    return converter;
}

@Bean
public ObjectMapper myObjectMapper() {
    //your custom ObjectMapper here
}
Run Code Online (Sandbox Code Playgroud)

在XML中,它是这样的:

<bean id="restOperations" class="org.springframework.web.client.RestTemplate">
    <property name="messageConverters">
        <util:list>
            <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
            <bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
            <bean class="org.springframework.http.converter.ResourceHttpMessageConverter"/>
            <bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"/>
            <bean class="org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter"/>
            <bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"/>
            <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
                <property name="objectMapper" ref="customObjectMapper"/>
            </bean>
        </util:list>
    </property>
</bean>

<bean id="customObjectMapper" class="org.codehaus.jackson.map.ObjectMapper"/>
Run Code Online (Sandbox Code Playgroud)

请注意,转换不是真正的1:1 - 我必须messageConverters在XML中显式创建列表,而使用@Configuration方法我可以引用现有的并简单地修改它.但这应该有效.

  • 不确定这是否仅仅是由于版本差异,但我相信Jackson转换器类的正确名称是MappingJackson*2*HttpMessageConverter (7认同)
  • @Justin:做我的客人 - 看看更新的答案. (2认同)
  • 我可能会避免在现有默认值的开头添加新的 mappingJacksonHttpMessageConverter,而是替换现有的 Jackson 消息转换器。否则,您最终会在列表中拥有 2 个 Jackson 消息转换器。 (2认同)

Mat*_*ger 22

如果你没有使用Spring IOC,你可以做这样的事情(Java 8):

ObjectMapper objectMapper = new ObjectMapper();
// configure your ObjectMapper here

RestTemplate restTemplate = new RestTemplate();    

MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
messageConverter.setPrettyPrint(false);
messageConverter.setObjectMapper(objectMapper);
restTemplate.getMessageConverters().removeIf(m -> m.getClass().getName().equals(MappingJackson2HttpMessageConverter.class.getName()));
restTemplate.getMessageConverters().add(messageConverter);
Run Code Online (Sandbox Code Playgroud)


mvo*_*zis 12

RestTemplate将初始化其默认消息转换器.您应该MappingJackson2HttpMessageConverter使用您自己的bean 替换它,它应该使用您想要使用的对象映射器.这对我有用:

@Bean
public RestTemplate restTemplate() {
    final RestTemplate restTemplate = new RestTemplate();

    //find and replace Jackson message converter with our own
    for (int i = 0; i < restTemplate.getMessageConverters().size(); i++) {
        final HttpMessageConverter<?> httpMessageConverter = restTemplate.getMessageConverters().get(i);
        if (httpMessageConverter instanceof MappingJackson2HttpMessageConverter){
            restTemplate.getMessageConverters().set(i, mappingJackson2HttpMessageConverter());
        }
    }

    return restTemplate;
}

@Bean
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
    MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
    converter.setObjectMapper(myObjectMapper());
    return converter;
}

@Bean
public ObjectMapper myObjectMapper() {
    // return your own object mapper
}
Run Code Online (Sandbox Code Playgroud)


Wim*_*uwe 8

使用 Spring Boot,它很简单:

RestTemplate template = new RestTemplateBuilder()
                            .additionalMessageConverters(new MappingJackson2HttpMessageConverter(objectMapper))
                            .build()
Run Code Online (Sandbox Code Playgroud)

(使用 Spring Boot 2.2.1 测试)


Oli*_*din 6

要完成其他答案:如果你ObjectMapper只是注册了杰克逊Module定制的串行/解串器,你可能想直接在现有注册模块ObjectMapperRestTemplate的默认MappingJackson2HttpMessageConverter如下(例如无DI但同样适用,如果使用DI):

    SimpleModule module = new SimpleModule();
    module.addSerializer(...);
    module.addDeserializer(...);

    MappingJackson2HttpMessageConverter messageConverter = restTemplate.getMessageConverters().stream()
                    .filter(MappingJackson2HttpMessageConverter.class::isInstance)
                    .map(MappingJackson2HttpMessageConverter.class::cast)
                    .findFirst().orElseThrow( () -> new RuntimeException("MappingJackson2HttpMessageConverter not found"));
    messageConverter.getObjectMapper().registerModule(module);
Run Code Online (Sandbox Code Playgroud)

这样您就可以完成原始文件的配置ObjectMapper(由Spring的完成Jackson2ObjectMapperBuilder),而不是替换它。