Unmarshalling nested list of xml items using JAXB

前端 未结 2 1596
情书的邮戳
情书的邮戳 2020-12-10 09:05

I\'ve got such xml construction which I need to convert into java objects using JAXB:


    
        
          


        
相关标签:
2条回答
  • 2020-12-10 09:39

    You will need to define a custom XmlAdapter. The complicated part in your case is that you want to map one XML element into multiple Java Element objects. This means that, in Java., your XmlAdapter needs to be configured for collection of Element objects. Assuming your example XML fragment is part of a document:

    <document>
       <elements> 
          <element>
              ....
          </element>
       <elements>
    </document>    
    

    Then you will need to configure the XmlAdapter for the List<Element> field in the Java Document class:

    class Document {
         @XmlJavaTypeAdapter(CustomAdapter.class)
         List<Element> elements;
    }
    

    Then you your CustomAdapter class can receive a list of Element objects (corresponding to the actual XML structure with the nested items) and produce a list of Element with the structure you want.

    For an example, check JAXB XmlAdapter – Customized Marshaling and Unmarshaling

    0 讨论(0)
  • 2020-12-10 09:58

    Main.java

    import java.io.StringReader;
    import java.util.ArrayList;
    import java.util.List;
    
    import javax.xml.bind.JAXBContext;
    import javax.xml.bind.JAXBException;
    import javax.xml.bind.Marshaller;
    import javax.xml.bind.Unmarshaller;
    
    
    public class Main {
    
        public static void main(String[] args) {
    
            List<Element> elementList = new ArrayList<Element>();
            List<Item> itemList = new ArrayList<Item>();
            Element element1 = new Element();
            Element element2 = new Element();
            Item item1 = new Item();
            Item item2 = new Item();
            Elements elements = new Elements();
    
            item1.setId(1);
            item1.setName("Test1");
            item2.setId(2);
            item2.setName("Test2");
            itemList.add(item1);
            itemList.add(item2);
    
            element1.setProperty1("prop1");
            element1.setProperty2("prop2");
            element1.setType(2);
            element1.setItems(itemList);
    
            element2.setProperty1("prop11");
            element2.setProperty2("prop22");
            element2.setType(22);
            element2.setItems(itemList);
    
            elementList.add(element1);
            elementList.add(element2);
    
            elements.setElements(elementList);
    
            try {
                System.out.println("------- Object to XML -----------\n");
                JAXBContext jaxbContext = JAXBContext.newInstance(Elements.class);
                Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
    
                // output pretty printed
                jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
    
                jaxbMarshaller.marshal(elements, System.out);
    
                System.out.println("\n------- XML to Object -----------\n");
    
                String xml = "<elements><element><items><item><id>1</id><name>Test1</name></item><item><id>2</id><name>Test2</name></item></items><property1>prop1</property1><property2>prop2</property2><type>2</type></element><element><items><item><id>1</id><name>Test1</name></item><item><id>2</id><name>Test2</name></item></items><property1>prop11</property1><property2>prop22</property2><type>22</type></element></elements>";
                StringReader reader = new StringReader(xml);
                Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
                Elements elementsOut = (Elements) jaxbUnmarshaller.unmarshal(reader);
                System.out.println(elementsOut);
    
            } catch (JAXBException e) {
                e.printStackTrace();
            }    
        }
    }
    

    Elements.java

    import java.lang.reflect.Field;
    import java.util.List;
    
    import javax.xml.bind.annotation.XmlElement;
    import javax.xml.bind.annotation.XmlRootElement;
    
    
    @XmlRootElement(name="elements")
    public class Elements {
    
        List<Element> elements;
    
        @XmlElement(name="element")
        public List<Element> getElements() {
            return elements;
        }
    
        public void setElements(List<Element> elements) {
            this.elements = elements;
        }
    
        @Override
        public String toString() {
            Field[] fields = this.getClass().getDeclaredFields();
            String res = "";
            try {
                for (Field field : fields) {
                    res += field.getName() + " :\n" + field.get(this);
                }
            } catch (Exception e) {
                e.printStackTrace(); 
            }
    
            return res;
        }
    }
    

    Element.java

    import java.lang.reflect.Field;
    import java.util.List;
    
    import javax.xml.bind.annotation.XmlElement;
    import javax.xml.bind.annotation.XmlElementWrapper;
    
    public class Element {
    
        Integer type;
        String property1;
        String property2;
        List<Item> items;
    
        public Integer getType() {
            return type;
        }
    
        public void setType(Integer type) {
            this.type = type;
        }
    
        public String getProperty1() {
            return property1;
        }
    
        public void setProperty1(String property1) {
            this.property1 = property1;
        }
    
        public String getProperty2() {
            return property2;
        }
    
        public void setProperty2(String property2) {
            this.property2 = property2;
        }
    
        @XmlElementWrapper(name="items")
        @XmlElement(name = "item")
        public List<Item> getItems() {
            return items;
        }
    
        public void setItems(List<Item> items) {
            this.items = items;
        }
    
        @Override
        public String toString() {
            Field[] fields = this.getClass().getDeclaredFields();
            String res = "\n";
            try {
                for (Field field : fields) {
                    res += field.getName() + " : " + field.get(this) + "\n";
                }
            } catch (Exception e) {
                e.printStackTrace(); 
            }
    
            return res;
        }
    }
    

    Item.java

    import java.lang.reflect.Field;
    
    
    public class Item {
        Integer id;
        String name; 
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        @Override
        public String toString() {
            Field[] fields = this.getClass().getDeclaredFields();
            String res = "{";
            try {
                for (Field field : fields) {
                    res += field.getName() + " : " + field.get(this);
                }
                res += "}";
            } catch (Exception e) {
                e.printStackTrace(); 
            }
    
            return res;
        }
    }
    

    Because the elements tag is root element you can't use @XmlElementWrapper, but items is not root, so you can use that there, thus you don't have to implement the Items class. Ignore the toString implementation, it's just to print the objects in a meaningful way.

    Object to XML Output

    ------- Object to XML -----------

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <elements>
        <element>
            <items>
                <item>
                    <id>1</id>
                    <name>Test1</name>
                </item>
                <item>
                    <id>2</id>
                    <name>Test2</name>
                </item>
            </items>
            <property1>prop1</property1>
            <property2>prop2</property2>
            <type>2</type>
        </element>
        <element>
            <items>
                <item>
                    <id>1</id>
                    <name>Test1</name>
                </item>
                <item>
                    <id>2</id>
                    <name>Test2</name>
                </item>
            </items>
            <property1>prop11</property1>
            <property2>prop22</property2>
            <type>22</type>
        </element>
    </elements>
    

    XML to Object Output

    ------- XML to Object -----------
    
    elements :
    [
    type : 2
    property1 : prop1
    property2 : prop2
    items : [{id : 1name : Test1}, {id : 2name : Test2}]
    , 
    type : 22
    property1 : prop11
    property2 : prop22
    items : [{id : 1name : Test1}, {id : 2name : Test2}]
    ]
    
    0 讨论(0)
提交回复
热议问题