json - How to deserialize a Timestamp as-is using Jackson Annotation in Java? -


i have field in java bean below @jsonformat jackson annotation:

@jsonformat(shape = jsonformat.shape.string, pattern="yyyy-mm-dd hh:mm") private timestamp createdon; 

when return timestamp, getting converted utc time in json response. lets on formatting timestamp , 2017-09-13 15:30 response getting returned 2017-09-13 10:00.

i know because of jackson annotation default takes system timezone , converts timestamp utc. (in case server belongs asia/calcutta time zone , offset +05:30 , jackson mapper subtracts 5 hrs , 30 minutes convert timestamp utc)

is there way return timestamp as-is, i.e, 2017-09-13 15:30 instead of 2017-09-13 10:00?

i've made test here, changing jvm default timezone asia/calcutta , creating class java.sql.timestamp field:

public class testtimestamp {      @jsonformat(shape = jsonformat.shape.string, pattern = "yyyy-mm-dd hh:mm")     private timestamp createdon;      // getter , setter } 

in other question told jdk 8 being used, tested in same version (if you're using version (jdk <= 7), check "not java 8" section in bottom). first created timestamp corresponds september 13th 2017, @ 10 in utc:

testtimestamp value = new testtimestamp(); // timestamp corresponds 2017-09-13t10:00:00 utc value.setcreatedon(timestamp.from(instant.parse("2017-09-13t10:00:00z"))); 

then serialized jackson's objectmapper:

objectmapper om = new objectmapper(); string s = om.writevalueasstring(value); 

the resulting string is:

{"createdon":"2017-09-13 10:00"}

note that, in generated json, output in utc (10 am). if deserialize json:

value = om.readvalue(s, testtimestamp.class); system.out.println(value.getcreatedon()); 

this print:

2017-09-13 15:30:00.0

that's because timestamp::tostring() method (which implicity called in system.out.println) prints timestamp in jvm default timezone. in case, default asia/calcutta, , 10 in utc same 15:30 in calcutta, output above produced.

as explained in my answer other question, timestamp object doesn't have timezone information. has number of nanoseconds since unix epoch (1970-01-01t00:00z or "january 1st 1970 @ midnight in utc").

using example above, if see value of value.getcreatedon().gettime(), you'll see it's 1505296800000 - that's number of milliseconds since epoch (to nanoseconds precision, there's method getnanos()).

this milliseconds value corresponds 10 in utc, 7 in são paulo, 11 in london, 7 pm in tokyo, 15:30 in calcutta , on. don't convert timestamp between zones, because millis value same everywhere in world.

what can change, though, representation of value (the corresponding date/time in specific timezone).

in jackson, can create custom serializers , deserializers (by extending com.fasterxml.jackson.databind.jsonserializer , com.fasterxml.jackson.databind.jsondeserializer), can have more control on how format , parse dates.

first create serializer formats timestamp jvm default timezone:

public class timestampserializer extends jsonserializer<timestamp> {      private datetimeformatter fmt = datetimeformatter.ofpattern("yyyy-mm-dd hh:mm");      @override     public void serialize(timestamp value, jsongenerator gen, serializerprovider serializers) throws ioexception, jsonprocessingexception {         // timestmap in default timezone         zoneddatetime z = value.toinstant().atzone(zoneid.systemdefault());         string str = fmt.format(z);          gen.writestring(str);     } } 

then create deserializer reads date in jvm default timezone , creates timestamp:

public class timestampdeserializer extends jsondeserializer<timestamp> {      private datetimeformatter fmt = datetimeformatter.ofpattern("yyyy-mm-dd hh:mm");      @override     public timestamp deserialize(jsonparser jsonparser, deserializationcontext ctxt) throws ioexception, jsonprocessingexception {         // parse localdatetime         localdatetime dt = localdatetime.parse(jsonparser.gettext(), fmt);         // date/time in default timezone         return timestamp.from(dt.atzone(zoneid.systemdefault()).toinstant());     } } 

i change field use these custom classes:

// remove jsonformat annotation @jsonserialize(using = timestampserializer.class) @jsondeserialize(using = timestampdeserializer.class) private timestamp createdon; 

now, when using same timestamp above (that corresponds 2017-09-13t10:00:00z). serializing produces:

{"createdon":"2017-09-13 15:30"}

note output corresponds local time in jvm default timezone (15:30 in asia/calcutta).

when deserializing json, same timestamp (corresponding 10 in utc).


this code uses jvm default timezone, can changed without notice, @ runtime, it's better make explicit 1 you're using.

the api uses iana timezones names (always in format region/city, asia/calcutta or europe/berlin), can create them using zoneid.of("asia/calcutta"). avoid using 3-letter abbreviations (like ist or pst) because ambiguous , not standard.

you can list of available timezones (and choose 1 fits best system) calling zoneid.getavailablezoneids().

if want change output correspond timezone, change zoneid.systemdefault() zone want. keep in mind same zone must used both serialize , deserialize, otherwise you'll wrong results.


not java 8?

if you're using java <= 7, can use threeten backport, great backport java 8's new date/time classes.

the difference package names (in java 8 java.time , in threeten backport org.threeten.bp), classes , methods names same.

there's difference: in java 8 timestamp class has methods toinstant() , from(), you'll need use org.threeten.bp.datetimeutils class make conversions:

public class timestampserializer extends jsonserializer<timestamp> {      private datetimeformatter fmt = datetimeformatter.ofpattern("yyyy-mm-dd hh:mm");      @override     public void serialize(timestamp value, jsongenerator gen, serializerprovider serializers) throws ioexception, jsonprocessingexception {         // timestmap in default timezone         zoneddatetime z = datetimeutils.toinstant(value).atzone(zoneid.systemdefault());         string str = fmt.format(z);          gen.writestring(str);     } }  public class timestampdeserializer extends jsondeserializer<timestamp> {      private datetimeformatter fmt = datetimeformatter.ofpattern("yyyy-mm-dd hh:mm");      @override     public timestamp deserialize(jsonparser jsonparser, deserializationcontext ctxt) throws ioexception, jsonprocessingexception {         // parse localdatetime         localdatetime dt = localdatetime.parse(jsonparser.gettext(), fmt);         // date/time in default timezone         return datetimeutils.tosqltimestamp(dt.atzone(zoneid.systemdefault()).toinstant());     } } 

Comments

Popular posts from this blog

angular - Ionic slides - dynamically add slides before and after -

minify - Minimizing css files -

Add a dynamic header in angular 2 http provider -