Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[eclipselink-users] help needed: unmarshal JSON into JaxB objects fails

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?


Back to the top