Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tell JAXB to unmarshal <xs:dateTime> to Date class using annotations

Tags:

java

jaxb

When using JAXB with Java-First, fields/properties of type java.util.Date are marshalled and unmarshalled as xs:dateTime and everything works as expected.

But if the type of the field/property is Object, JAXB unmarshals xs:dateTimeto XMLGregorianCalendarImpl.

I need to find a way that makes JAXB unmarshal date-time values to java.util.Date by itself using annotations. Otherwise, I'll need to go through all unmarshalled values in each use case.

Even if there were some after-unmarshall-hook to define on the classes containing Object fields and convert the instances manually would be good. But I couldn't find anything that can be used this way either.

Note that I have limited access to the JAXB context, as it is used inside Apache CXF.

like image 516
Iravanchi Avatar asked Oct 17 '10 13:10

Iravanchi


People also ask

How do you Unmarshal with JAXB?

UNMARSHALLING. To unmarshal an xml string into a JAXB object, you will need to create an Unmarshaller from the JAXBContext, then call the unmarshal() method with a source/reader and the expected root object.

What is JAXB annotations?

JAXB provides a fast and convenient way to marshal (write) Java objects into XML and unmarshal (read) XML into objects. It supports a binding framework that maps XML elements and attributes to Java fields and properties using Java annotations.

Which annotation is used to map a Java class object to XML element?

The JAXB annotations defined in the javax. xml. bind. annotations package can be used to customize Java program elements to XML schema mapping.


2 Answers

In addition to Blaise Doughan's answer:

I could finally figure this out, thanks for help from Blaise Doughan. Actually his answer works with just a small change: if there's several types expected to be unmarshalled as the Object property, there needs to be multiple @XmlElement annotations placed on it using @XmlElements annotation.

Here's my code now:

@XmlElements
        ({
                @XmlElement(name = "dateValue",    type = Date.class),
                @XmlElement(name = "stringValue",  type = String.class),
                @XmlElement(name = "booleanValue", type = Boolean.class),
                @XmlElement(name = "listValue",    type = ArrayList.class),
                @XmlElement(name = "bytesValue",   type = Byte[].class)
        })
public Object getFieldValue()
{
    return fieldValue;
}

Note: specifying "name" is required for this to work, since there should be a way for the marshaller / unmarshaller to identify the type of the content.

There are two minor issues here:

  1. You need to specify a list of all of the types expected (which is logical, given the case of marshalling)

  2. There's no way to specify a single name for this property. In my case, where JAXB is used in CXF web services, code generated from WSDL in .NET names this field as "Item". If there was a way, for example, to wrap the XML elements in another one which has a single name, the generated code could be a little bit nicer.

like image 177
Iravanchi Avatar answered Nov 14 '22 22:11

Iravanchi


You can set the type property on @XmlElement.

@XmlElement(type=Date.class)
public Object getGenericDateProperty() {
    return date;
}

Edit:

Since you don't know the type you could use an XmlAdapter. If the unmarshalled value is an XMLGregorianCalendar convert it to a Date. For more info on XmlAdapter see:

  • http://bdoughan.blogspot.com/2010/07/xmladapter-jaxbs-secret-weapon.html
like image 42
bdoughan Avatar answered Nov 15 '22 00:11

bdoughan