Skip to main content

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

Hi

What happens if you don't set the JSON_NAMESPACE_PREFIX_MAPPER property at all and remove the "urn:x-hp:2009:software:data_model:opr:type:" part of the @type attributes so that everything is just "@type":"event_statistic_record" or is the JSON input fixed?  I'm not sure where the urn:x-hp:2009:software:data_model:opr:type in the document maps to so if you could also include OprResourceBase.java, OprEvtStatisticRecord.java and if have a package-info in your package that might help so I can reproduce the issue you are seeing.  Was the JSON in your example created by MOXy or something else...just wondering if marshaling is working for  or if it's just an unmarshal problem?

Thanks
Denise

 

From: Edelmann, Falk (HP Software) [mailto:falk.edelmann@xxxxxx]
Sent: Monday, October 14, 2013 10:31 AM
To: eclipselink-users@xxxxxxxxxxx
Subject: [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