Hallo,
It seems that the current version of
EclipseLink MOXy (version 2.5.1) has an issue with
un-marshaling JSON documents where the prefix of default
namespace is set to empty String. I have set up everything to
marshal JAXB objects into XML/JSON documents as well as to
un-marshal XML/JSON documents into JAXB objects. Everything
works except for the un-marshaling of large JSON documents
(objects containing arrays of nested objects) if the default
namespace prefix is set to an empty string. We do not want a
namespace prefix for our object properties as it much easier
to access these properties in our HTML UIs via _javascript_. Our
un-marshal code looks as following at the moment:
public final static Map<String,
String> getNamespacePrefixes() {
Map<String, String> prefixMap =
new HashMap<String, String>();
prefixMap["http://www.mytesturl.com/2013/software/data_model"]
= “”; // if we set this to a non-empty string, it works. Why
is this needed?
prefixMap["http://www.w3.org/2001/XMLSchema-instance"]
= “xsi”;
prefixMap["http://www.w3.org/2001/XMLSchema"]
= “xs”;
return prefixMap;
}
unmarshaller =
jaxbContext.createUnmarshaller();
unmarshaller.setProperty(UnmarshallerProperties.AUTO_DETECT_MEDIA_TYPE,
Boolean.TRUE);
unmarshaller.setProperty(UnmarshallerProperties.JSON_ATTRIBUTE_PREFIX,
"@");
unmarshaller.setProperty(UnmarshallerProperties.JSON_NAMESPACE_PREFIX_MAPPER,
getNamespacePrefixes());
unmarshaller.setProperty(UnmarshallerProperties.JSON_NAMESPACE_SEPARATOR,
‘:’);
unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT,
Boolean.TRUE);
unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE,
MediaType.APPLICATION_JSON);
// String jsonDoc = // get the json as a
string
Object obj = unmarshaller.unmarshal(new
StringReader(jsonDoc));
OprResourceBase jaxbObject =
(OprResourceBase)(obj instanceof JAXBElement ? obj.value :
obj);
with “OprResourceBase” as the base class
for all our JAXB annotated classes.
This code works only for simple objects
(that is, objects that have only properties of type string,
date, number, or boolean). However, as soon as the objects
contain other objects and especially arrays of objects, the
un-marshaled object is not correct, that is, the call to the
“unmarshal” method returns without an exception but the
returned object contains invalid data. For example,
The following sample JSON document is not
correctly un-marshaled:
{
"event_statistics" : {
"@type" :
"urn:x-hp:2009:software:data_model:opr:type:event_statistics",
"@version" : "1.0",
"start" : "2012-11-17T12:00:00",
"end" : "2013-06-05T12:00:00",
"statistic" : [ {
"@type" :
"urn:x-hp:2009:software:data_model:opr:type:event_statistic_record",
"@version" : "1.0",
"start" : "2013-02-06T12:00:00",
"interval" : 86400000,
"type" : "RECEIVED",
"value" : 7,
"server" : "DPS"
}, {
"@type" :
"urn:x-hp:2009:software:data_model:opr:type:event_statistic_record",
"@version" : "1.0",
"start" : "2013-02-07T12:00:00",
"interval" : 86400000,
"type" : "RECEIVED",
"value" : 14,
"server" : "DPS"
}, {
"@type" :
"urn:x-hp:2009:software:data_model:opr:type:event_statistic_record",
"@version" : "1.0",
"start" : "2013-02-08T12:00:00",
"interval" : 86400000,
"type" : "RECEIVED",
"value" : 21,
"server" : "DPS"
}, {
"@type" :
"urn:x-hp:2009:software:data_model:opr:type:event_statistic_record",
"@version" : "1.0",
"start" : "2013-02-09T12:00:00",
"interval" : 86400000,
"type" : "RECEIVED",
"value" : 28,
"server" : "DPS"
},
...
]
}
}
The corresponding JAXB annotated Java class
looks as following:
@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement(name =
OprEvtStatistics.XML_NAME)
@XmlType(name = OprEvtStatistics.XML_TYPE,
propOrder = {"startDate",
"endDate", "statistics", "aggregation", "any"})
public final class OprEvtStatistics extends
OprResourceBase
{
private static final long
serialVersionUID = -7981235285649760399L;
public static final String VERSION =
"1.0";
public static final String XML_NAME =
"event_statistics";
public static final String XML_TYPE =
XML_NAME + "_type";
public static final String TYPE =
OprResourceBase.BASE_TYPE + XML_NAME;
public static final String BASE_REF_TYPE
= OprResourceBase.BASE_REF_TYPE + XML_NAME + ":";
public static final URI TYPE_URI =
URI.create(TYPE);
private Date m_startDate;
private Date m_endDate;
private List<OprEvtStatisticRecord>
m_stats;
private OprEvtAggregation m_aggregation;
private List<Object> m_any;
private Map<QName, Object>
m_anyAttribute;
public OprEvtStatistics()
{
super(TYPE_URI, VERSION);
}
@XmlAnyElement(lax = true)
public List<Object> getAny()
{
return m_any;
}
@Override
public void setAny(List<Object>
any)
{
m_any = any;
}
@XmlAnyAttribute
public Map<QName, Object>
getAnyAttribute()
{
return m_anyAttribute;
}
@Override
public void setAnyAttribute(Map<QName,
Object> anyAttribute)
{
m_anyAttribute = anyAttribute;
}
@XmlElement(name = "start")
public Date getStartDate()
{
return m_startDate;
}
public void setStartDate(Date value)
{
this.m_startDate = value;
}
@XmlElement(name = "end")
public Date getEndDate()
{
return m_endDate;
}
public void setEndDate(Date value)
{
this.m_endDate = value;
}
@XmlElement(name = "statistic")
public List<OprEvtStatisticRecord>
getStatistics()
{
return m_stats;
}
public void
setStatistics(List<OprEvtStatisticRecord> value)
{
this.m_stats = value;
}
@XmlElement(name = "aggregation")
public OprEvtAggregation getAggregation()
{
return m_aggregation;
}
public void
setAggregation(OprEvtAggregation value)
{
this.m_aggregation = value;
}
…
}
After un-marshaling the above JSON
document, I get a JAXB object with start and end date
correctly set but the array of statistics (property
“statistic”) is empty. Instead, this arrays is stored in
property “any” and the elements of this arrays also contain
only incomplete data. If I use a prefix for the default
namespace, however, everything works as expected.
So, can someone help? Did I miss anything
in the EclipseLink MOXy documentation? Or is it a known issue
that will be fixed in a future release?