How to unmarshal xml message with bad parent/child model

前端 未结 1 832
小蘑菇
小蘑菇 2021-01-03 00:49

I am trying to unmarshal a 3rd party XML payload into a class. The problem is that the payload has a parent/child relationship and the root node, the parent and the children

相关标签:
1条回答
  • 2021-01-03 01:06

    Short Answer

    The exception is due to a field/property collision. You can either annotate the properties (get methods) or set the following annotation on your type:

    @XmlAccessorType(XmlAccessType.FIELD)
    public class Directory {
      ...
    }
    

    Long Answer

    JAXB's default access type is PUBLIC_MEMBER this means that JAXB will map all public fields (instance variables) and properties (get/set methods).

    public class Foo {
    
        private String bar;
    
        public String getBar() {
            return bar;
        }
    
        public void setBar(String bar) {
            this.bar = bar;
        }
    
    }
    

    If you annotate a field:

    public class Foo {
    
        @XmlAttribute
        private String bar;
    
        public String getBar() {
            return bar;
        }
    
        public void setBar(String bar) {
            this.bar = bar;
        }
    
    }
    

    Then JAXB will think it has two bar properties mapped and thrown an exception:

    Exception in thread "main" com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
    Class has two properties of the same name "bar"
        this problem is related to the following location:
            at public java.lang.String example.Foo.getBar()
            at example.Foo
        this problem is related to the following location:
            at private java.lang.String example.Foo.bar
            at example.Foo
    

    The solution is to annotate the property and set the XmlAccessType type to FIELD

    @XmlAccessorType(XmlAccessType.FIELD)
    public class Foo {
    
        @XmlAttribute
        private String bar;
    
        public String getBar() {
            return bar;
        }
    
        public void setBar(String bar) {
            this.bar = bar;
        }
    
    }
    

    Your Model

    Directory

    import java.util.ArrayList;
    import java.util.List;
    
    import javax.xml.bind.annotation.XmlAccessorType;
    import javax.xml.bind.annotation.XmlAccessType;
    import javax.xml.bind.annotation.XmlElement;
    import javax.xml.bind.annotation.XmlRootElement;
    
    @XmlRootElement(name="Directory")
    @XmlAccessorType(XmlAccessType.FIELD)
    public class Directory {
        private int id;
        private String name;
    
        @XmlElement(name="Directory")
        private List<Directory> directories = new ArrayList<Directory>();
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public List<Directory> getDirectories() {
            return directories;
        }
    
        public void setDirectories(List<Directory> directories) {
            this.directories = directories;
        }
    
    }
    

    Demo

    import java.io.File;
    import javax.xml.bind.JAXBContext;
    import javax.xml.bind.Marshaller;
    import javax.xml.bind.Unmarshaller;
    
    public class Demo {
    
        public static void main(String[] args) throws Exception {
            JAXBContext jc = JAXBContext.newInstance(Directory.class);
    
            Unmarshaller unmarshaller = jc.createUnmarshaller();
            Directory directory = (Directory) unmarshaller.unmarshal(new File("input.xml"));
    
            Marshaller marshaller = jc.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            marshaller.marshal(directory, System.out);
        }
    
    }
    
    0 讨论(0)
提交回复
热议问题