【问题标题】:Spring MVC - receiving XML Objects and deserialzing into CollectionSpring MVC - 接收 XML 对象并反序列化为 Collection
【发布时间】:2018-05-23 18:35:02
【问题描述】:

我正在尝试使用特定的标签/对象层次结构反序列化 XML 有效负载(SOAP 消息的主体,但仅此而已)。尝试将展开的对象聚合到 List 中时,会引发 MismatchedInputException。

示例负载

<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>

Java 对象是

public class LibraryRequest {
    private LibraryProfile libraryProfile;
    @XmlElement(name = "libraryProfile")
    public LibraryProfile getLibraryProfile(){
    ...
    }
// setters

public class LibraryProfile {
    // constructors, getters & setters for primitive types 

    private List<BookInfo> bookInfos;
    public List<BookInfo> getBookInfo(){
        return this.BookInfos;
    }
    // rest of the functions

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

我是否可以使用 JAXB 将 XML 序列分组到 Java 集合/列表中,如果不能,我是否可以使用 Jackson 的 XML 功能将未包装的 XML 标记分组到 Java 集合中?

主要目标是使用让 XML 请求进入 Spring 控制器并将 XML 序列正确反序列化为 Java 列表/集合。任何建议都会有所帮助。

我使用的是 Spring Boot 1.5.8(后来的版本给我带来了不同的麻烦)和 Jackson 版本 2.9.5

【问题讨论】:

    标签: java xml spring spring-mvc jackson2


    【解决方案1】:

    这是基于XmlElement explanation from actimem.com

    机制解释: - @XmlElement 仅在字段名称不等于 xml 标记名称时才需要。 - 如果您想将字段 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
    }
    

    根据您的问题输入(我跳过了&lt;libraryRequest&gt; 以保持示例简短)

      <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'}
    

    【讨论】:

    • 谢谢,终于成功了!我已切换到 Jackson,因为我的项目需要 XML 和 JSON 支持,并且使用 @JacksonXMLElementWrapper(localName="...", useWrapping=false) 注释有效
    猜你喜欢
    • 2014-05-25
    • 1970-01-01
    • 1970-01-01
    • 2020-05-10
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    • 2010-11-11
    相关资源
    最近更新 更多