Retrofit GSON serialize Date from json string into java.util.date

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?

  • Variables with underline
  • Correct use of setEmtpyView in AdapterView
  • Android setBackgroundTintList on pre-lollipop devices
  • Unable to compile my android project
  • Error Message: emulator-arm.exe has stopped working
  • Balloon chat application issues
  • Related posts:

    How to create fixed footer in android layout?
    CoordinatorLayout status bar padding disappears from ViewPager 2nd page
    SwipeRefreshLayout with NestedScrollView and LinearLayout
    Android: Rotate image in imageview by an angle
    Does the presenter having knowledge of the Activity / Context a bad idea in the MVP pattern?
    Get width and height of components in Fragment view
  • Programatically enabling/disabling screen rotations in Android
  • Gap between left drawable and text in a EditText
  • exit android application programmatically
  • Add custom headers to WebView resource requests - android
  • “Unable to start service Intent” error when starting service from an Activity in Android
  • How to update SimpleAdapter in Android
  • 6 Solutions collect form web for “Retrofit GSON serialize Date from json string into java.util.date”

    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(gson))
    .build();
    

    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

    @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();
    

    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;
    }
    

    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]
    

    Quite literally if you already have an Date object with the name “created_at” in the class you are creating then it is this 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 overriding needed.

    You can define two new classes like this:

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

    and

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

    Your POJO will be like this:

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

    Finally set your custom 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());
    
    Android Babe is a Google Android Fan, All about Android Phones, Android Wear, Android Dev and Android Games Apps and so on.