Spring MVC - 接收XML对象并反序列化为Collection

时间:2018-05-23 18:35:03

标签: java xml spring spring-mvc jackson2

我正在尝试使用特定的标记/对象​​层次结构反序列化XML有效负载(SOAP消息的主体,但没有别的)。尝试将未包装的对象聚合到List中时,会抛出MismatchedInputException。

示例有效负载

int

Java对象

<libraryRequest>
  <libraryProfile>
    <libraryId>
    <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>...</currentBooks>
  </libraryProfile>
</libraryRequest>

我的问题是我不知道XML有效负载中会有多少个currentBooks标签,并且它们不会包含在包装元素中。我需要跟踪每个currentBook元素,这就是我使用Collection的原因,但我无法使用currentBooks标记中包含的信息正确填充集合。

我是否可以使用JAXB将XML序列分组为Java Collection / List,如果没有,我是否可以使用Jackson的XML功能将未打包的XML标记分组到Java Collection中?

主要目标是使用XML请求进入Spring Controller并将XML序列正确地反序列化为Java List / Collection。任何建议都会有帮助。

我正在使用Spring Boot 1.5.8(后来的版本以不同的方式给我带来麻烦),而Jackson版本为2.9.5

1 个答案:

答案 0 :(得分:2)

这基于XmlElement explanation from actimem.com

机械师解释说:   - 仅当字段名称不等于xml标记名称时才需要@XmlElement。   - 如果您想将字段newBookInfo重命名为newestBook但不更改xml,只需重命名字段并使用@XmlElement(name="newBookInfo")对其进行注释即可   - @XmlElementWrapper明确不用于建议JAXB它应该直接在父节点中搜索列表标记

XML表示类Book

@XmlAccessorType(XmlAccessType.FIELD)
public static class Book {
    private String bookId;
    private String bookTitle;
    // ... accessors and toString 
}

LibraryProfile

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public static class LibraryProfile {
    private String libraryId;
    private String libraryName;
    private Book newBookInfo;
    // the trick is NOT to use @XmlElementWrapper here
    private List<Book> currentBooks;
    private String foobar; // just to show a tag after the list 
    // ... accessors
}

基于您的问题的输入(我跳过<libraryRequest>以保持示例简短)

  <libraryProfile>
    <libraryId>1</libraryId>
    <libraryName>library of alexandria</libraryName>
    <newBookInfo>
      <bookId>42</bookId>
      <bookTitle>the answer</bookTitle>
    </newBookInfo>
    <currentBooks>
      <bookId>2</bookId>
      <bookTitle>the second</bookTitle>
    </currentBooks>
    <currentBooks>
      <bookId>1</bookId>
      <bookTitle>the first</bookTitle>
    </currentBooks>
    <foobar>test-foo</foobar>
  </libraryProfile>

这里是测试类:

package com.stackoverflow.answer;

import javax.xml.bind.JAXB;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.StringReader;

public class Tester {

    public static final String INPUT = "..."; // here goes your xml

    public static void main(String[] args) throws Exception {
        LibraryProfile lib = JAXB.unmarshal(new StringReader(INPUT), LibraryProfile.class);
        System.out.println(lib.getLibraryName() + " currently contains");
        System.out.println(lib.getCurrentBooks());
        System.out.println("the newest book is: " + lib.getNewBookInfo());
    }
}

现在输出

library of alexandria currently contains
[Book{bookId='2', bookTitle='the second'}, Book{bookId='1', bookTitle='the first'}]
the newest book is: Book{bookId='42', bookTitle='the answer'}