简体   繁体   English

jaxb 按类型解组到对象

[英]jaxb unmarshal to object by type

I want to parse out different types based on xml, when header=1 then User, header=2 then Order etc. for example:我想根据xml解析出不同的类型,当header=1然后User,header=2然后Order等,例如:

<entity>
  <header>1</header>
  <body>
    <userId>1</userId>
    <userName>jonh</userName>
    ...
  <body>
</entity>
<entity>
  <header>2</header>
  <body>
    <orderId>1</orderId>
    <orderNo>20200101</orderNo>
    ...
  <body>
</entity>

How to implement this function?如何实现这个功能?

Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
Object object = unmarshaller.unmarshal(xml);

I would try this: provide the type when unmarshalling.我会试试这个:在解组时提供类型。 So maybe do something like this: create a transient facade object:所以也许做这样的事情:创建一个瞬态外观对象:

public class XmlEntityFacade {

   private int header;
   private Object body;

   //getters and setters...

}

And then cast this type while unmarshalling:然后在解组时投射这种类型:

...
XmlEntityFacade facade = (XmlEntityFacade) unmarshaller.unmarshal(xml);

Then you can access the value of the by calling .getHeader() and body with .getBody() (getters that you have provided XmlEntityFacade class).然后,您可以通过调用 .getHeader() 和使用 .getBody()(您提供的 XmlEntityFacade 类的获取器)调用 body 来访问 的值。 And then depending on the value cast the required type to the Object.然后根据值将所需的类型转换为对象。

public class TwiceUnmarshalTest {

    @Data
    @ToString
    public static abstract class HeaderResponse {
        private String header;
    }

    @XmlRootElement(name = "entity")
    @XmlAccessorType(XmlAccessType.FIELD)
    public static class XmlHeaderResponse extends HeaderResponse {
    }

    private final String xml = "<entity>" +
            "  <header>2</header>" +
            "  <body>" +
            "    <orderId>1</orderId>" +
            "    <orderNo>2020</orderNo>" +
            "  </body>" +
            "</entity>";

    @SuppressWarnings("unchecked")
    public static <T> T unmarshal(Reader reader, Class<T> typeClass) throws Exception {
        JAXBContext jaxbContext = JAXBContext.newInstance(typeClass);
        Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
        return (T) unmarshaller.unmarshal(reader);
    }

    @Test
    public void headerResponse() throws Exception {
        HeaderResponse response = unmarshal(new StringReader(xml), XmlHeaderResponse.class);
        System.out.println(response);
    }

    @ToString(callSuper = true)
    public static abstract class Response<T> extends HeaderResponse {
        @XmlAnyElement(lax = true)
        public T body;
    }

    @Data
    @XmlRootElement(name = "body")
    public static class Order {
        private String orderId;
        private String orderNo;

    }

    @XmlRootElement(name = "entity")
    @XmlSeeAlso({Order.class})
    public static class OrderResponse extends Response<Order> {
    }

    @Test
    public void response() throws Exception {
        XmlHeaderResponse response = unmarshal(new StringReader(xml), XmlHeaderResponse.class);
        System.out.println(response);
        //TwiceUnmarshalTest.HeaderResponse(header=2)
        if (response.getHeader().equals("2")) {
            OrderResponse orderResponse = unmarshal(new StringReader(xml), OrderResponse.class);
            System.out.println(orderResponse);
  //TwiceUnmarshalTest.Response(super=TwiceUnmarshalTest.HeaderResponse(header=2), body=TwiceUnmarshalTest.Order(orderId=1, orderNo=2020))
        }
    }
}

unmarshal twice, just get the header first, then get the entity.解组两次,只需先获取标题,然后获取实体。 Not very good but can be used.不是很好,但可以使用。

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

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