Mohse Taheri
Mohse Taheri

Reputation: 741

jackson serialize different time zones into single time zone

I have multiple timezones and I want to have them exactly after serialization, but jackson convert them into single time zone if I set DateFormat all zones convert to context time zone and if I don't set DateFormat all zones convert to UTC (zero time zone).

I know that we have DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE in deserialization and we can disable it but I can't find something like this in SerializationFeature.

Is there anyway that I can tell jackson to don't convert timezones?

here is my test class:

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;

import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import java.text.SimpleDateFormat;
import java.util.TimeZone;


public class Test {

    public static class flight {
        private XMLGregorianCalendar dateDeparture;
        private XMLGregorianCalendar dateArrival;

        public XMLGregorianCalendar getDateDeparture() {
            return dateDeparture;
        }

        public void setDateDeparture(XMLGregorianCalendar dateDeparture) {
            this.dateDeparture = dateDeparture;
        }

        public XMLGregorianCalendar getDateArrival() {
            return dateArrival;
        }

        public void setDateArrival(XMLGregorianCalendar dateArrival) {
            this.dateArrival = dateArrival;
        }
    }

    public static void main(String[] args) throws DatatypeConfigurationException, JsonProcessingException {
        XMLGregorianCalendar dateDeparture = DatatypeFactory.newInstance().newXMLGregorianCalendar(2018,1,22,10,15,0,0, TimeZone.getTimeZone("Asia/Istanbul").getRawOffset()/1000/60);
        XMLGregorianCalendar dateArrival = DatatypeFactory.newInstance().newXMLGregorianCalendar(2018,1,22,13,30,0,0,TimeZone.getTimeZone("Asia/Dubai").getRawOffset()/1000/60);
        System.out.println("Local Departure Time=" + dateDeparture);
        System.out.println("Local Arrival Time=" + dateArrival);

        flight flight = new flight();
        flight.setDateDeparture(dateDeparture);
        flight.setDateArrival(dateArrival);

        XmlMapper xmlMapper = new XmlMapper();
        xmlMapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        xmlMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ssZ"));
        String xml = xmlMapper.writeValueAsString(flight);
        System.out.println(xml);
    }
}

here is the output:

Local Departure Time=2018-01-22T10:15:00.000+03:00
Local Arrival Time=2018-01-22T13:30:00.000+04:00
<flight><dateDeparture>2018-01-22T10:45:00+0330</dateDeparture><dateArrival>2018-01-22T01:00:00+0330</dateArrival></flight>

Upvotes: 1

Views: 1240

Answers (1)

A.Shaheri
A.Shaheri

Reputation: 450

The only way I could think of is to create your own serialize module so to be able to handle XMLGregorianCalendar serialization all by yourself. Unfortunately Java has proven not to be good in handling dates.

public class XMLCalendarSerializer extends StdSerializer<XMLGregorianCalendar> {
    public XMLCalendarSerializer() {
        this((Class)null);
    }

    public XMLCalendarSerializer(Class<XMLGregorianCalendar> t) {
        super(t);
    }

   public void serialize(XMLGregorianCalendar value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
        DateFormat dateFormatt = provider.getConfig().getDateFormat();
        if(dateFormatt.getCalendar() == null) {
            jgen.writeString(value.toString());
        } else {
            SimpleDateFormat dateFormat = (SimpleDateFormat)dateFormatt;
            GregorianCalendar a = value.toGregorianCalendar();
            Date date = value.toGregorianCalendar().getTime();
            dateFormat.setTimeZone(TimeZone.getTimeZone(value.getTimeZone(value.getTimezone()).getDisplayName()));
            jgen.writeString(dateFormat.format(date));
        }

    }
}

and the module class would be like:

public class XMLCalendarModule extends SimpleModule {
    private static final String NAME = "CustomXMLCalendarModule";
    private static final VersionUtil VERSION_UTIL = new VersionUtil() {
};

    public XMLCalendarModule() {
        super("CustomXMLCalendarModule", VERSION_UTIL.version());
        this.addSerializer(XMLGregorianCalendar.class, new XMLCalendarSerializer());
    }
}

and you can simply register this module like:

xmlMapper.registerModule(new XMLCalendarModule());

Upvotes: 2

Related Questions