Retrofit GSON Date series from json string in java.util.date

I use the Retrofit library for my REST calls. Most of what I did was smooth as butter, but for some reason I am having problems converting JSON time strings to java.util.Date objects. The JSON that goes 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 to java.util.Date objects ?

+65
java json android gson retrofit
Aug 27 '13 at 18:36
source share
6 answers
 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 configure your own Gson parser for upgrades. Read more here: Modified site

Look at Ondreju's answer to see how to implement this in modification 2.

+123
May 24 '14 at 10:24
source share

@gderaco responds to upgrade to version 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(); 
+69
Jan 25 '16 at 0:39
source share

Here is how I did it:

Create a DateTime class that extends the date, and then write your own deserializer:

 public class DateTime extends java.util.Date { public DateTime(long readLong) { super(readLong); } public DateTime(Date date) { super(date.getTime()); } } 

Now for the part of the deserializer where we register the 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 the RestAdapter, do the following:

 new RestAdapter.Builder().setConverter(gsonWithDate()); 

Your Foo should look like this:

 class Foo { Date date; DateTime created_at; } 
+11
Jul 05 '14 at 9:22
source share

Gson can only process one datetime format (those specified in the builder), plus iso8601 if parsing with a custom format is not possible. So the solution may be to write your own 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); } } 

The final step is to instantiate the Gson with the correct 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] 
+7
Sep 02 '13 at 23:26
source share

Quite literally, if you already have a Date object named "created_at" in the class you are creating, this is easy:

 Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").create(); YourObject parsedObject1 = gson.fromJson(JsonStringYouGotSomehow, YourObject.class); 

And you're done. no complicated redefinition is required.

+1
Nov 11 '14 at 21:31
source share

You can define two new classes:

 import java.util.Date; public class MyDate extends Date { } 

and

 import java.util.Date; public class CreatedAtDate extends Date { } 

Your POJO will look like this:

 import MyDate; import CreatedAtDate; public class Foo { MyDate date; CreatedAtDate created_at; } 

Finally, configure your deserializer:

 public class MyDateDeserializer implements JsonDeserializer<Date> { public static final SimpleDateFormat sServerDateDateFormat = new SimpleDateFormat("yyyy-MM-dd"); @Override public MyDate deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { if (json != null) { final String jsonString = json.getAsString(); try { return (MyDate) sServerDateDateFormat.parse(jsonString); } catch (ParseException e) { e.printStackTrace(); } } return null; } } 

and

 GsonBuilder builder = new GsonBuilder(); builder.registerTypeAdapter(MyDate.class, new MyDateDeserializer()); 
+1
Jun 08 '15 at 15:37
source share



All Articles