简体   繁体   English

如何在 Spring RestTemplate 中使用 JAXB 注释?

[英]How do I use JAXB annotations with Spring RestTemplate?

I'm trying to automatically deserialize XML formatted response using Spring's RestTemplate.我正在尝试使用 Spring 的 RestTemplate 自动反序列化 XML 格式的响应。 I'm using Jackson's jackson-dataformat-xml module, for which Spring Boot is set to auto-configure.我正在使用 Jackson 的jackson-dataformat-xml模块,Spring Boot 设置为自动配置。 I want to use JAXB annotations in the class I want to deserialize to, but it won't seem to work.我想在要反序列化的类中使用 JAXB 注释,但它似乎不起作用。 Here's a sample of what I want the class to look like:这是我希望班级看起来像的示例:

@XmlRootElement(name="Book")
public class Book {

    @XmlElement(name="Title")
    private String title;
    @XmlElement(name="Author")
    private String author;

}

This is based on the following XML sample:这基于以下 XML 示例:

<Book>
    <Title>My Book</Title>
    <Author>Me</Author>
</Book>

However, with class annotated like that above, the fields are always set null .但是,对于像上面那样注释的类,字段始终设置为null I did some experiments and found out that the deserialization works if I use Jackson's @JsonProperty to annotate the child elements:我做了一些实验,发现如果我使用 Jackson 的@JsonProperty来注释子元素,反序列化是有效的:

@XmlRootElement(name="Book")
public class Book {

    @JsonProperty("Title")
    private String title;
    @JsonProperty("Author")
    private String author;

}

It works, but somehow I feel like it's kind of awkward.它有效,但不知何故,我觉得这有点尴尬。 Is there a way to get the JAXB annotations work like in my first example?有没有办法让 JAXB 注释像我的第一个例子一样工作?

Jackson provides jackson-module-jaxb-annotations module for the XML databinding to work with JAXB annotations. Jackson 为 XML 数据绑定提供了jackson-module-jaxb-annotations模块,以便与 JAXB 注释一起使用。 However, I'm not sure how to setup the ObjectMapper being used by RestTemplate to use this module.但是,我不确定如何设置RestTemplate使用的ObjectMapper以使用此模块。

To address this issue, I needed to register an instance of JaxbAnnotationModule to every ObjectMapper used by converters added to Spring's RestTemplate .为了解决这个问题,我需要向添加到 Spring 的RestTemplate转换器使用的每个ObjectMapper注册一个JaxbAnnotationModule实例。 The class is included in Jackson's jackson-module-jaxb-annotations module, which I added to my build through Gradle.该类包含在 Jackson 的jackson-module-jaxb-annotations模块中,我通过 Gradle 添加到我的构建中。

With the dependency added to my project, what I did next was to configure the RestTemplate used by my application.将依赖项添加到我的项目中后,我接下来要做的是配置我的应用程序使用的RestTemplate The ObjectMapper instances are being used by MappingJackson2XmlHttpMessageConverter s configured automatically by Spring. Spring 自动配置的MappingJackson2XmlHttpMessageConverter正在使用ObjectMapper实例。 I had to register JaxbAnnotationModule instance to each ObjectMapper used in every converter, so the first task was to find all MappingJackson2XmlHttpMessageConverter s using:我必须将JaxbAnnotationModule实例注册到每个转换器中使用的每个ObjectMapper ,因此第一个任务是使用以下命令查找所有MappingJackson2XmlHttpMessageConverter s:

//create module
JaxbAnnotationModule jaxbAnnotationModule = new JaxbAnnotationModule();

restTemplate.getMessageConverters().stream().filter(converter -> {
    return converter instanceof MappingJackson2XmlHttpMessageConverter;
})

Once I had all the relevant converters, I then registered the module to each of their ObjectMappers :一旦我拥有了所有相关的转换器,我ObjectMappers模块注册到他们的每个ObjectMappers

forEach(converter -> {
    ((MappingJackson2XmlHttpMessageConverter) converter)
            .getObjectMapper()
            .register(jaxbAnnotationModule);
});

I suspect that in second case Spring simply ignores root level JAXB annotation, because by default Jackson will resolve name of the class properly.我怀疑在第二种情况下,Spring 只是忽略了根级别的 JAXB 注释,因为默认情况下 Jackson 会正确解析类的名称。

In order to use JAXB annotations you have to use library jackson-xc为了使用 JAXB 注释,您必须使用库jackson-xc

<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-xc</artifactId>
</dependency>

These artilces may be also useful:这些文章也可能有用:

1) http://wiki.fasterxml.com/JacksonJAXBAnnotations 1) http://wiki.fasterxml.com/JacksonJAXBAnnotations

2) http://springinpractice.com/2011/12/06/jackson-json-jaxb2-xml-spring 2) http://springinpractice.com/2011/12/06/jackson-json-jaxb2-xml-spring

3) How can we configure the internal Jackson mapper when using RestTemplate? 3) 使用RestTemplate 时如何配置内部Jackson 映射器?

If solution by @Psycho Punch still not working for you, This is another alternative:如果@Psycho Punch 的解决方案仍然不适合您,这是另一种选择:

  • add com.fasterxml.jackson.dataformat:jackson-dataformat-xml dependency.添加com.fasterxml.jackson.dataformat:jackson-dataformat-xml依赖项。
  • use XmlMapper instead of ObjectMapper to your MappingJackson2XmlHttpMessageConverter .使用 XmlMapper 而不是 ObjectMapper 到您的MappingJackson2XmlHttpMessageConverter For example:例如:

     XmlMapper xmlMapper = new XmlMapper(); xmlMapper.registerModule(new JaxbAnnotationModule()); forEach(converter -> { ((MappingJackson2XmlHttpMessageConverter) converter).setObjectMapper(xmlMapper) });

HTH HTH

If someone still have to deal with this kind of issue, Springboot provide an elegant solution :如果有人仍然需要处理此类问题,Springboot 提供了一个优雅的解决方案:

Any beans of type com.fasterxml.jackson.databind.Module are automatically registered with the auto-configured Jackson2ObjectMapperBuilder and are applied to any ObjectMapper instances that it creates.任何 com.fasterxml.jackson.databind.Module 类型的 bean 都会自动注册到自动配置的 Jackson2ObjectMapperBuilder 并应用于它创建的任何 ObjectMapper 实例。 This provides a global mechanism for contributing custom modules when you add new features to your application.当您向应用程序添加新功能时,这提供了用于贡献自定义模块的全局机制。

So adding this in one of your configuration class should be enough:因此,在您的配置类之一中添加它就足够了:

@Bean
public Module jaxbModule() {
    return new JaxbAnnotationModule();
}

Source: https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto-customize-the-jackson-objectmapper来源: https : //docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto-customize-the-jackson-objectmapper

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM