Retrofit GSON serialize Date from json string into java.util.date
Solution 1
Gson gson = new GsonBuilder()
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss")
.create();
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(API_BASE_URL)
.setConverter(new GsonConverter.create(gson))
.build();
Or the Kotlin equivalent:
val gson = GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss").create()
RestAdapter restAdapter = Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.build()
.create(T::class.java)
You can set your customized Gson parser to retrofit. More here: Retrofit Website
Look at Ondreju's response to see how to implement this in retrofit 2.
Solution 2
@gderaco's answer updated to retrofit 2.0:
Gson gson = new GsonBuilder()
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss")
.create();
Retrofit retrofitAdapter = new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
Solution 3
Here is how I did it:
Create DateTime class extending Date and then write a custom deserializer:
public class DateTime extends java.util.Date {
public DateTime(long readLong) {
super(readLong);
}
public DateTime(Date date) {
super(date.getTime());
}
}
Now for the deserializer part where we register both Date and DateTime converters:
public static Gson gsonWithDate(){
final GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(Date.class, new JsonDeserializer<Date>() {
final DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
@Override
public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
try {
return df.parse(json.getAsString());
} catch (final java.text.ParseException e) {
e.printStackTrace();
return null;
}
}
});
builder.registerTypeAdapter(DateTime.class, new JsonDeserializer<DateTime>() {
final DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Override
public DateTime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
try {
return new DateTime(df.parse(json.getAsString()));
} catch (final java.text.ParseException e) {
e.printStackTrace();
return null;
}
}
});
return builder.create();
}
And when you create your RestAdapter, do the following:
new RestAdapter.Builder().setConverter(gsonWithDate());
Your Foo should look like this:
class Foo {
Date date;
DateTime created_at;
}
Solution 4
Gson can handle only one datetime format (those specified in builder) plus the iso8601 if parsing with custom format is not possible. So, a solution could be to write your custom deserializer. To solve your problem I defined:
package stackoverflow.questions.q18473011;
import java.util.Date;
public class Foo {
Date date;
Date created_at;
public Foo(Date date, Date created_at){
this.date = date;
this.created_at = created_at;
}
@Override
public String toString() {
return "Foo [date=" + date + ", created_at=" + created_at + "]";
}
}
with this deserializer:
package stackoverflow.questions.q18473011;
import java.lang.reflect.Type;
import java.text.*;
import java.util.Date;
import com.google.gson.*;
public class FooDeserializer implements JsonDeserializer<Foo> {
public Foo deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
String a = json.getAsJsonObject().get("date").getAsString();
String b = json.getAsJsonObject().get("created_at").getAsString();
SimpleDateFormat sdfDate = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat sdfDateWithTime = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
Date date, created;
try {
date = sdfDate.parse(a);
created = sdfDateWithTime.parse(b);
} catch (ParseException e) {
throw new RuntimeException(e);
}
return new Foo(date, created);
}
}
Final step is to create a Gson
instance with right adapter:
package stackoverflow.questions.q18473011;
import com.google.gson.*;
public class Question {
/**
* @param args
*/
public static void main(String[] args) {
String s = "{ \"date\": \"2013-07-16\", \"created_at\": \"2013-07-16T22:52:36Z\"}";
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(Foo.class, new FooDeserializer());
Gson gson = builder.create();
Foo myObject = gson.fromJson(s, Foo.class);
System.out.println("Result: "+myObject);
}
}
My result:
Result: Foo [date=Tue Jul 16 00:00:00 CEST 2013, created_at=Tue Jul 16 22:52:36 CEST 2013]
jpotts18
Updated on July 23, 2020Comments
-
jpotts18 almost 4 years
I am using the Retrofit library for my REST calls. Most of what I have done has been smooth as butter but for some reason I am having issues converting JSON timestamp strings into
java.util.Date
objects. The JSON that is coming in looks like this.{ "date": "2013-07-16", "created_at": "2013-07-16T22:52:36Z", }
How can I tell Retrofit or Gson to convert these strings into
java.util.Date objects
? -
Mohit Jain almost 10 yearsPlease explain your code in brief so that it is more useful for OP and other readers.
-
Juan Saravia over 9 yearsThanks! I only had to change from
return df.parse(json.getAsString());
tolong timeStamp = Long.parseLong(json.getAsString()); return new java.util.Date(timeStamp);
-
Zapnologica over 8 yearsHow can I do this for all of my requests? So Add it to my
ServiceGenerator
? -
Alireza Mirian over 8 yearsThis actually doesn't apply locale for me.
2016-02-11T13:42:14.401Z
gets deserialized to a date object which is for13:42:14
in my locale. -
Zapnologica over 7 yearsI have tried this, Downloaded items seems to be working now. But when I post a Json Object to the server. Will it then remove my time zone?
-
LukaszTaraszka about 7 yearsI spent so much time for detecting problem with crashing my app with no reason after implementing this solution. When I copied and paste dete format something changed a quotation mark from 'T' to ’T’ - there is a different - watch carefully!
-
LukaszTaraszka about 7 yearsWatch for quotation mark when copying date format - I had problem with that!
-
NickUnuchek almost 7 yearsGreat! Thank you!
-
Farid almost 6 yearsWhat if I have 15-20 fields inside Foo (including custom objects), I have to deserialize them manually, right. That kills the purpose of Gson then.
-
Farid almost 6 yearsYou should have tried it with Retrofit first before "And you're done. no complicated overriding needed."
-
maddy23285 over 4 yearsFind this after hours of searching and worked like a charm. Thanks
-
Bruno over 3 yearsWhy have you not included the 'Z' parameter for timezone in the end of the string that goes on 'setDateFormat'? I wasted 2 hours here to discover that i should use '"yyyy-MM-dd'T'HH:mm:ss'Z'" instead.