我试图将第三方XML有效负载解组到一个类中.问题是有效负载具有父/子关系,根节点,父节点和子节点都具有相同的元素名称.以下是有效负载的示例.
<?xml version="1.0" encoding="UTF-8"?> <Directory> <id>2</id> <name>Media</name> <Directory> <id>5</id> <name>Default_Content</name> <Directory> <id>9</id> <name>Images</name> </Directory> <Directory> <id>8</id> <name>Icons</name> </Directory> <Directory> <id>6</id> <name>Additional_Content</name> </Directory> </Directory> <Directory> <id>12</id> <name>IC</name> </Directory> </Directory>
所以我试图注释一个类,以便JAXB / JAX-RS可以将其解组为有用的东西.
我尝试过这样的事情
@XmlRootElement(name="Directory") public class Directory { private int id; private String name; @XmlElement(name="Directory"); private List<Directory> directories = new ArrayList<Directory>(); }
但是,可以预见的是,由于具有两个具有相同名称的属性,它会抛出IllegalAnnotationException.
关于如何使用JAXB / JAX-RS干净地处理这个烂摊子的任何想法,或者我应该自己解析它?
简答
例外是由于字段/属性冲突.您可以注释属性(获取方法)或在类型上设置以下注释:
@XmlAccessorType(XmlAccessType.FIELD) public class Directory { ... }
答案很长
JAXB的默认访问类型是PUBLIC_MEMBER,这意味着JAXB将映射所有公共字段(实例变量)和属性(get / set方法).
public class Foo { private String bar; public String getBar() { return bar; } public void setBar(String bar) { this.bar = bar; } }
如果您注释一个字段:
public class Foo { @XmlAttribute private String bar; public String getBar() { return bar; } public void setBar(String bar) { this.bar = bar; } }
然后JAXB会认为它有两个bar属性映射并抛出异常:
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
解决方案是注释属性并将XmlAccessType类型设置为FIELD
@XmlAccessorType(XmlAccessType.FIELD) public class Foo { @XmlAttribute private String bar; public String getBar() { return bar; } public void setBar(String bar) { this.bar = bar; } }
你的模特
目录
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; } }
演示
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); } }