如何防止MappingJackson2XmlHttpMessageConverter接管序列化?

How to prevent MappingJackson2XmlHttpMessageConverter from taking over serialization?

我正在使用 RestTemplate 与几个 REST 服务交互,其中一些 accept/return JSON 和一些 XML。为此,我添加了 Jackson's dataformat-xml module as a dependency (along with the JAXB annotations module)。 RestTemplate 自动包含 MappingJackson2XmlHttpMessageConverter(在 RestTemplate 构造函数中完成)。

这会导致一些对象在调用

时用作 request 参数
RestTemplate.postForObject(String url, Object request, Class<T> responseType, Object... uriVariables)`

序列化为 XML 并且请求的内容类型设置为 application/xml。例如:

MyObject request = ...;
String url = ...;
MyResponseObject response = restTemplate.postForObject(url, request, MyResponseObject.class);

RestTemplate 尝试将 MyObject 序列化为 XML 并将请求媒体类型设置为 application/xml.

问题是,我们调用的许多服务不接受 XML(他们期望 JSON)。所以现在我在类路径上有 MappingJackson2XmlHttpMessageConverter,它优先于 JSON 转换器,这使得对 JSON 服务的调用失败。

我想我可以更改我的调用代码以传递媒体类型显式设置为 JSON 的 HttpEntity 而不是我的简单数据对象,但这有点丑陋(样板)并且会意味着改变相当多的服务调用代码。

有没有办法

A) 更改 MessageConverter 的优先级,使标准 Jackons (JSON) 优先于 MappingJackson2XmlHttpMessageConverter

B) 防止 MappingJackson2XmlHttpMessageConverter 声称它可以序列化我不希望它序列化的对象

?

我可以看到两个选项:

  • 用你想要的 HttpMessageConverter 创建一个 RestTemplate,按照你希望它们使用的顺序(检查 HttpEntityRequestCallback.doWithRequest 它们按照它们在列表中的顺序使用并且将使用第一个匹配转换器

  • 按照您的建议,使用 HttpEntity 并将 Content-Type header 设置为您想要的 mime 类型。

我认为使用助手用你的 object 和正确的 Content-Type header 创建一个 HttpEntity 会更安全:

public class HttpEntityHelper {

    public static <T> HttpEntity<T> jsonHttpEntity(T body) {
        MultiValueMap<String, String> headers = new LinkedMultiValueMap();
        headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
        return new HttpEntity(body, headers);
    }
}