Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
MOXy offers the @XmlInverseReference
extension that can be used to support bidirectional relationships in both XML and JSON binding.
JAVA MODEL
Customer
Customer
has a collection of PhoneNumber
objects.
package forum12312395;
import java.util.List;
import javax.xml.bind.annotation.*;
@XmlRootElement
public class Customer {
private List<PhoneNumber> phoneNumbers;
@XmlElement(name="phone-number")
public List<PhoneNumber> getPhoneNumbers() {
return phoneNumbers;
}
public void setPhoneNumbers(List<PhoneNumber> phoneNumbers) {
this.phoneNumbers = phoneNumbers;
}
}
PhoneNumber
Each PhoneNumber
object maintains a back pointer to the Customer
object. This property is annotated with @XmlInverseReference
.
package forum12312395;
import javax.xml.bind.annotation.XmlValue;
import org.eclipse.persistence.oxm.annotations.XmlInverseReference;
public class PhoneNumber {
private String value;
private Customer customer;
@XmlValue
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
@XmlInverseReference(mappedBy="phoneNumbers")
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
}
jaxb.properties
To use MOXy as your JAXB provider you need to include a file called jaxb.properties
in the same package as your domain model with the following entry (see: http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html):
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
INPUT
Below are the documents that we will unmarshal in this example
input.xml
<?xml version="1.0" encoding="UTF-8"?>
<customer>
<phone-number>555-WORK</phone-number>
<phone-number>555-HOME</phone-number>
</customer>
input.json
{
"customer" : {
"phone-number" : ["555-HOME", "555-WORK"]
}
}
DEMO
package forum12312395;
import javax.xml.bind.*;
import javax.xml.transform.stream.StreamSource;
import org.eclipse.persistence.jaxb.UnmarshallerProperties;
import org.eclipse.persistence.oxm.MediaType;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Customer.class);
// JSON
Unmarshaller jsonUnmarshaller = jc.createUnmarshaller();
jsonUnmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, MediaType.APPLICATION_JSON);
StreamSource json = new StreamSource("src/forum12312395/input.json");
Customer customerFromJSON = (Customer) jsonUnmarshaller.unmarshal(json);
for(PhoneNumber phoneNumber : customerFromJSON.getPhoneNumbers()) {
System.out.println(phoneNumber.getCustomer());
}
// XML
Unmarshaller xmlUnmarshaller = jc.createUnmarshaller();
StreamSource xml = new StreamSource("src/forum12312395/input.xml");
Customer customerFromXML = (Customer) xmlUnmarshaller.unmarshal(xml);
for(PhoneNumber phoneNumber : customerFromXML.getPhoneNumbers()) {
System.out.println(phoneNumber.getCustomer());
}
}
}
OUTPUT
Below is the output from running the demo code. As you can see the customer
property is populated on all of the PhoneNumber
objects.
forum12312395.Customer@3ef38fd1
forum12312395.Customer@3ef38fd1
forum12312395.Customer@320eef20
forum12312395.Customer@320eef20
FOR MORE INFORMATION