XMLGregorianCalendar is changing the format while using GSON

856 Views Asked by At

My pojo class having some field whose datatype is XMLGregorianCalendar.

 protected XMLGregorianCalendar driverBirthDate; //the value is  -"1967-08-13-05:45"

While I am converting the object to json string using GSON the output is generating something else for this field.

Gson gson = new Gson();    
String str = gson.toJson(pojoObj);

After convert -

"driverBirthDate": {
                    "day": 13,
                    "hour": -2147483648,
                    "minute": -2147483648,
                    "month": 8,
                    "second": -2147483648,
                    "timezone": -345,
                    "year": 1967
                }

But I need the exact same format what pojo object holds.

Any quick help will be great.

1

There are 1 best solutions below

0
On

The reason why Gson outputs the XMLGregorianCalendar as JSON object is because it does not have a built-in adapter for this type and therefore falls back to the reflection based adapter which emits the values of all fields of the class.

You can solve this by creating a custom TypeAdapter:

public class XMLGregorianCalendarTypeAdapter extends TypeAdapter<XMLGregorianCalendar> {
    private final DatatypeFactory datatypeFactory;
    
    public XMLGregorianCalendarTypeAdapter(DatatypeFactory datatypeFactory) {
        this.datatypeFactory = Objects.requireNonNull(datatypeFactory);
    }
    
    @Override
    public XMLGregorianCalendar read(JsonReader in) throws IOException {
        return datatypeFactory.newXMLGregorianCalendar(in.nextString());
    }
    
    @Override
    public void write(JsonWriter out, XMLGregorianCalendar value) throws IOException {
        out.value(value.toXMLFormat());
    }
}

(DatatypeFactory is javax.xml.datatype.DatatypeFactory)

And then create the Gson instance using a GsonBuilder on which you register that adapter:

// Assumes that either the DatatypeFactory instance is thread-safe or you are
// not using the Gson instance from multiple threads
DatatypeFactory datatypeFactory = ...;
Gson gson = new GsonBuilder()
    .registerTypeHierarchyAdapter(
        XMLGregorianCalendar.class,
        // Call `nullSafe()` to make adapter handle null values on its own
        new XMLGregorianCalendarTypeAdapter(datatypeFactory).nullSafe()
    )
    .create();

Using registerTypeHierarchyAdapter here is necessary because XMLGregorianCalendar is an abstract class and your type adapter is supposed to handle the subclasses as well.