[英]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 的解决方案仍然不适合您,这是另一种选择:
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.