title: Custom gson deserializer for Date never gets called
body: <p>As far as I can tell, gson does not automatically serialize and deserialize java.util.Date objects into ISO strings like "yyyy-MM-ddTHH:mm:ssZ" or for example "2014-04-15T18:22:00-05:00". So in order for me to communicate dates properly between my client (using Retrofit with gson) and server, I need to specify the DateFormat to gson. Here is what I've done:</p>
  
  <pre><code>// code defining the creation of a RestAdapter
  // ...
  new GsonBuilder()
      .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
      .create()
  </code></pre>
  
  <p>Adding the .setDateFormat line was enough to get gson to properly deserialize timestamp strings into Date objects. However, it did not serialize Date objects into timestamp strings. So I assumed that I would have to create a custom serializer like so:</p>
  
  <pre><code>// code defining the creation of a RestAdapter
  // ...
  new GsonBuilder()
      .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
      .registerTypeAdapter(Date.class, new DateSerializer())
      .create()
  </code></pre>
  
  <p>and the DateSerializer class:</p>
  
  <pre><code>class DateSerializer implements JsonSerializer&lt;Date&gt; {
      @Override
      public JsonElement serialize(Date arg0, Type arg1, JsonSerializationContext arg2) {
          SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.US);
          return new JsonPrimitive(df.format(arg0));
      }
  }
  </code></pre>
  
  <p>Unfortunately, the serialize function is ignored. Instead gson formats the date as a string like "Tues Mar 15 18:22:00 EST 2014". So to test, I tried replacing the serialize function with:</p>
  
  <pre><code>public JsonElement serialize(Date arg0, Type arg1, JsonSerializationContext arg2) {
      throw new RuntimeException("Serialize function called!");
  }
  </code></pre>
  
  <p>But of course that RuntimeException is never thrown.</p>
  
  <p>Does anyone know why my serialize function is ignored? I think I read somewhere that for some types a registerTypeAdapter will be ignored if there is one defined for a superclass, but since this is java.util.Date I would be confused if that was the problem. I'm probably just doing something stupid, but I probably don't know Date or gson well enough to realize it.</p>
  
  <p>EDIT: Provided more context around the code below:</p>
  
  <p><strong>MyApplication.java</strong></p>
  
  <pre><code>public class MyApplication extends Application {
      public static RestAdapter restAdapter;
      public static The1Api the1Api;
  
      public static void createRestAdapter(String server_url){
          // enable cookies
          CookieManager cookieManager = new CookieManager();
          cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
          CookieHandler.setDefault(cookieManager);
  
          // create rest adapter
          restAdapter = new RestAdapter.Builder()
              .setEndpoint(server_url)
              .setConverter(new GsonConverter(new GsonBuilder()
                      .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
                      .registerTypeAdapter(Date.class, new DateSerializer())
                      .create()))
              .setLogLevel(LogLevel.FULL)
              .setLog(new ResponseInterceptor())
              .build();
  
          // create API
          the1Api = restAdapter.create(The1Api.class);
      }
  }
  </code></pre>
  
  <p><strong>The1Api.java</strong></p>
  
  <pre><code>public interface The1Api {
      /* Chat */
  
      public class PublicMessage {
          String from_user;
          String message;
          Date time;
          Integer microsecond;
          Boolean in_1_percent;
      }
      public class PublicMessageList {
          Integer last_message_id;
          ArrayList&lt;PublicMessage&gt; messages;
      }
  
      @GET("/chat/get_public_messages/")
      public PublicMessageList getPublicMessages(
              @Query("last_message_id") Integer last_message_id, // optional
              @Query("since") Date since, // optional
              @Query("max") Integer max // optional
              );   
  
      // ...
  }
  </code></pre>
  
  <p><strong>LoginActivity.java</strong></p>
  
  <pre><code>public class LoginActivity extends Activity {
      // ...
  
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          Crashlytics.start(this);
          MyApplication.createRestAdapter(getString(R.string.server_url));
          setContentView(R.layout.activity_login);
      }
  
      @Override
      protected void onPostCreate(Bundle savedInstanceState){
          super.onPostCreate(savedInstanceState);
  
          Thread thread = new Thread(){
              @Override
              public void run(){
                  ArrayList&lt;The1Api.PublicMessage&gt; publicMessages = MyApplication.the1Api.getPublicMessages(null, null, null).messages;
                  for (The1Api.PublicMessage m : publicMessages){
                      Log.d("The1", "[" + m.time.toString() + "] " + m.from_user + ": " + m.message);
                  }
                  // when the following line gets executed, my server receives a request including the date below,
                  // but the server does not understand the format of the date because it does not get serialized properly
                  MyApplication.the1Api.getPublicMessages(null, new Date(1000000000), null);
              }
          };
          thread.start();
      }
  
      // ...    
  }
  </code></pre>
  
  <p><strong>DateSerializer.java</strong></p>
  
  <pre><code>class DateSerializer implements JsonSerializer&lt;Date&gt; {
      @Override
      public JsonElement serialize(Date arg0, Type arg1, JsonSerializationContext arg2) {
          SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.US);
          return new JsonPrimitive(df.format(arg0));
      }
  }
  </code></pre>
  
  <p>EDIT 2: No solutions as of yet, but as a workaround you can manually convert the Date to some other format before sending it. In the comments Kalel suggested converting it to a String, I converted it to a Long (number of seconds since UNIX epoch).</p>