I'm trying to find a way to correctly map the following XML/JSON document to an equivalent JAXB/Moxy annotated class.
NOTE that the model element of the document, which in my example describes a person, is freeform, i.e. might be any kind of XML element/JSON object, which is not statically known.
XML document:
<form>
<title>Person Form</title>
<model>
<person>
<name>John</name>
<surname>Smith</surname>
<address>
<street>Main St.</street>
<city>NY</city>
<country>USA</country>
</address>
<person>
</model>
</form>
Equivalent JSON document:
{
"title":"Form Title",
"model":{
"person":{
"name":"John",
"surname":"Smith",
"address":{
"street":"Main St.",
"city":"NY",
"country":"USA"
}
}
}
}
I thought to map the model field as a Map, where the values might be primitive types or Map themselves. This mapping would be enough expressive for my needs.
I tried to play with the @XmlReadTransformer, @XmlWriteTransformer MOXY annotations, but with no success (the record parameter I get in the buildAttributeValue is always null)
@XmlRootElement @XmlAccessorType(XmlAccessType.FIELD)
public class Form {
private String title;
private Model model;
....getters and setters....
}
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Model {
@XmlElement
@XmlReadTransformer(transformerClass = Transformer.class)
@XmlWriteTransformers({ @XmlWriteTransformer(xmlPath = "./*", transformerClass = Transformer.class) })
private Map<String, Object> data;
public Map<String, Object> getData() {
return data;
}
public void setData(Map<String, Object> data) {
this.data = data;
}
public static class Transformer implements AttributeTransformer, FieldTransformer {
private AbstractTransformationMapping tm;
public Transformer() {
}
@Override
public void initialize(AbstractTransformationMapping tm) {
this.tm = tm;
}
@Override
public Map<String, Object> buildAttributeValue(Record r, Object o,
Session s) {
Map<String, Object> data = new HashMap<String, Object>();
// TODO: ????
return data;
}
@Override
public Object buildFieldValue(Object arg0, String arg1, Session arg2) {
// TODO
return null;
}
}
}
Can you suggest me a proper way of solve this problem or a different way of modeling the "model" field?
Is Person (or whatever other class you have) a class that is available at runtime? Could the XML/JSON be modified slightly to include a type attribute that indicates which class it corresponds to? If so the example here may help you http://blog.bdoughan.com/2012/02/xmlanyelement-and-xmladapter.html
Your Model would then have something like this
and using the ParameterAdapter in the linked example you would need to include the type attribute that it is using in the XML and JSON
or