Spring MVC中XML无包装标签反序列化为Java集合的问题
如何用JAXB或Jackson XML反序列化无外层包装的XML列表到Java集合?
我在尝试反序列化SOAP消息体的XML负载(仅消息体部分)时遇到了MismatchedInputException,问题出在将无外层包装的<currentBooks>元素聚合到List的时候。
示例XML负载
<libraryRequest> <libraryProfile> <libraryId>...</libraryId> <libraryName>...</libraryName> <newBookInfo> <bookId>...</bookId> <bookTitle>...</bookTitle> <datePublished>...</datePublished> </newBookInfo> <currentBooks> <bookId>...</bookId> <bookTitle>...</bookTitle> <datePublished>...</datePublished> </currentBooks> <currentBooks> <bookId>...</bookId> <bookTitle>...</bookTitle> <datePublished>...</datePublished> </currentBooks> <!-- 更多currentBooks元素 --> </libraryProfile> </libraryRequest>
对应的Java对象结构
public class LibraryRequest { private LibraryProfile libraryProfile; @XmlElement(name = "libraryProfile") public LibraryProfile getLibraryProfile() { return libraryProfile; } // setter 方法 } public class LibraryProfile { // libraryId、libraryName、newBookInfo 的构造器、getter/setter private List<BookInfo> bookInfos; public List<BookInfo> getBookInfos() { return bookInfos; } // setter 方法 } public class BookInfo { private String bookId; private String bookTitle; private String datePublished; // 构造器、getter/setter }
我的核心问题是:XML中的<currentBooks>标签没有外层包装元素,且数量不确定,需要把每个<currentBooks>都映射到LibraryProfile里的List<BookInfo>集合,但目前无法正确填充数据。请问能否用JAXB实现?如果不行的话,用Jackson XML功能可以做到吗?最终目标是让Spring Controller接收XML请求后能正确反序列化为Java集合。我使用的是Spring Boot 1.5.8和Jackson 2.9.5。
解决方案
方法一:使用JAXB实现映射
JAXB可以通过@XmlElement注解直接指定列表元素的名称,不需要外层包装。你需要修改LibraryProfile类的bookInfos字段的注解:
public class LibraryProfile { // 其他字段的getter/setter private List<BookInfo> bookInfos; @XmlElement(name = "currentBooks") // 指定XML中对应的元素名称 public List<BookInfo> getBookInfos() { return bookInfos; } public void setBookInfos(List<BookInfo> bookInfos) { this.bookInfos = bookInfos; } }
这样JAXB在反序列化时,会自动把所有<currentBooks>元素收集到bookInfos这个List里,不需要额外的外层包装标签。
另外要确保BookInfo类的字段也正确加上@XmlElement注解,对应XML里的子元素:
public class BookInfo { @XmlElement(name = "bookId") private String bookId; @XmlElement(name = "bookTitle") private String bookTitle; @XmlElement(name = "datePublished") private String datePublished; // 无参构造器(JAXB必须要求)、getter/setter }
方法二:使用Jackson XML实现映射
如果你更倾向于用Jackson处理XML,同样可以通过注解配置来解决无包装列表的问题:
- 首先确保你的Spring Boot项目已经引入了Jackson XML依赖:
<dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> <version>2.9.5</version> </dependency>
- 修改
LibraryProfile类,使用Jackson XML的专属注解:
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; public class LibraryProfile { // 其他字段的getter/setter private List<BookInfo> bookInfos; // 禁用外层包装,指定每个元素的XML名称 @JacksonXmlElementWrapper(useWrapping = false) @JacksonXmlProperty(localName = "currentBooks") public List<BookInfo> getBookInfos() { return bookInfos; } public void setBookInfos(List<BookInfo> bookInfos) { this.bookInfos = bookInfos; } }
BookInfo类同样需要用Jackson的注解映射字段:
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; public class BookInfo { @JacksonXmlProperty(localName = "bookId") private String bookId; @JacksonXmlProperty(localName = "bookTitle") private String bookTitle; @JacksonXmlProperty(localName = "datePublished") private String datePublished; // 构造器、getter/setter }
- 在Spring Controller中,确保正确配置请求接收:
import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @RestController public class LibraryController { @PostMapping(value = "/library", consumes = MediaType.APPLICATION_XML_VALUE) public void handleLibraryRequest(@RequestBody LibraryRequest request) { // 处理请求,此时request中的libraryProfile.bookInfos已经正确填充了所有currentBooks数据 } }
注意事项
- JAXB要求实体类必须有无参构造器,否则会反序列化失败;Jackson虽然不强制,但建议也加上无参构造器避免潜在问题。
- 如果你同时使用JAXB和Jackson,要注意Spring Boot默认的消息转换器优先级,避免冲突。如果优先使用Jackson XML,可以配置
MappingJackson2XmlHttpMessageConverter作为主要的XML转换器。
内容的提问来源于stack exchange,提问作者user8811650
相关产品推荐
相关产品推荐

