How to decouple an XML message with a bad parent / child model

I am trying to decouple a third-party XML payload into a class. The problem is that the payload has a parent / child relationship, and the root node, parent and all children have the same element name. Here is an example payload.

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

So, I'm trying to annotate a class, so JAXB / JAX-RS can unleash this into something useful.

I tried something like this

 @XmlRootElement(name="Directory") public class Directory { private int id; private String name; @XmlElement(name="Directory"); private List<Directory> directories = new ArrayList<Directory>(); } 

But, as predicted, it throws an IllegalAnnotationException due to the presence of two properties with the same name.

Any ideas on how I can use JAXB / JAX-RS to fully deal with this mess, or should I just parse it myself?

+6
source share
1 answer

Short answer

The exception is due to a collision of fields / properties. You can either annotate properties (retrieval methods) or set the following annotation for your type:

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

Long answer

The default JAXB access type PUBLIC_MEMBER means that JAXB will display 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 assume that it has two bar properties that were displayed and an exception was thrown:

 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

Catalog

 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); } } 
+13
source

Source: https://habr.com/ru/post/888570/


All Articles