guochaiqi / google-gson

Automatically exported from code.google.com/p/google-gson
0 stars 0 forks source link

GsonBuilder setDateFormat ignored #230

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. Build a gson with setDateFormat
Date date = new Date();
Gson gson = new GsonBuilder().setDateFormat("MM/dd/yyyy").create();
System.out.println(gson.toJson(date));

What is the expected output? What do you see instead?
Expected is "08/27/2010"
Date results in standard format: "Aug 27, 2010 10:21:32 AM"

What version of the product are you using? On what operating system?
1.5

Please provide any additional information below.
It works ok in 1.4 but when I change to 1.5 it ignores the setDateFormat() 
method

Original issue reported on code.google.com by tradefie...@gmail.com on 27 Aug 2010 at 2:38

GoogleCodeExporter commented 9 years ago
It still happens in version 1.6 when the object is within a collection. 

Original comment by alxm...@gmail.com on 4 Jan 2011 at 11:55

GoogleCodeExporter commented 9 years ago
We encountered this problem as well with our server, except that we expected 
the dates to be serialized by a custom adapter.  The weird thing is that 
everything was going fine in our unit tests.
We spent a couple of hours doing remote debugging and looking at the code. It 
seems at some point during serialization, our java.util.Date objects were 
handled as if they were java.sql.Date objects.
So they were serialized following the default pattern for java.sql.Date, which 
matches our unexpected output and the unexpected output in the comment above.
I think the problem appeared in gson 1.5, where support for sql dates was 
added, and is maybe related to the fact that java.sql.Date extends 
java.util.Date...
A workaround for us was to register the same adapter for java.sql.Date than for 
java.util.Date:

Gson gson = new GsonBuilder()
        .......
        .registerTypeAdapter(Date.class, new DateTypeAdapter())
        .registerTypeAdapter(java.sql.Date.class, new DateTypeAdapter())
        .......
        .create();

Original comment by pfrangi...@gmail.com on 3 Feb 2011 at 8:40

GoogleCodeExporter commented 9 years ago
That woule be cool to fix that in 1.7!

Original comment by pfrangi...@gmail.com on 3 Feb 2011 at 8:41

GoogleCodeExporter commented 9 years ago
This should be a higher priority defect since working with dates is very 
common. Hope this will be fixed as soon as possible.

Original comment by inancsev...@gmail.com on 4 Feb 2011 at 10:07

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
JsonSerializationVisitor.visitFieldUsingCustomHandler(FieldAttributes, Type, 
Object) line: 195

Object obj = f.get(parent);

In f.get() method, "field.get(instance)" returns Timestamp object for 
java.util.Date class.

field is java.lang.reflect.Field

and then

ObjectTypePair.getActualTypeIfMoreSpecific(Type, Class<?>) line: 87 

if (typeAsClass.isAssignableFrom(actualClass)) {
    type = actualClass;
}

The "type" which is "java.util.Date" is assigned by "actualClass" which is 
"java.sql.Timestamp".

Original comment by das...@gmail.com on 4 Feb 2011 at 9:58

GoogleCodeExporter commented 9 years ago
On startup when sets datePattern for GsonBuilder, code creates dateTypeAdapter 
for Date.class in GsonBuilder.addTypeAdaptersForDate method:

if (datePattern != null && !"".equals(datePattern.trim())) {
   dateTypeAdapter = new DefaultDateTypeAdapter(datePattern);
} 
...
if (dateTypeAdapter != null) {
  if (!serializers.hasSpecificHandlerFor(Date.class)) {
      serializers.register(Date.class, dateTypeAdapter);
  }
....

but line 530 of GsonBuilder while "serializers" is being filled with 
defaultSerializers, dateTypeAdapter for Timestamp.class is created with default 
SimpleDateFormat.

Original comment by das...@gmail.com on 4 Feb 2011 at 11:40

GoogleCodeExporter commented 9 years ago
Hi again, 

Gson is trying to serialize more specific field type. When reading Date type 
from database the Date field of domain object is set to java.sql.Timestamp or 
java.sql.Date

A workaround is to register custom adapter according to your Date instance type 
read from database:

registerTypeAdapter(Timestamp.class, new DateSerializer())
or
registerTypeAdapter(java.sql.Date.class, new DateSerializer())

in source code we can change GsonBuilder.addTypeAdaptersForDate method like 
this:

....
   if (dateTypeAdapter != null) {
      if (!serializers.hasSpecificHandlerFor(Date.class)) {
          serializers.register(Date.class, dateTypeAdapter);
      }
      if (!serializers.hasSpecificHandlerFor(Timestamp.class)) {
          serializers.register(Timestamp.class, dateTypeAdapter);
      }
      if (!serializers.hasSpecificHandlerFor(java.sql.Date.class)) {
          serializers.register(java.sql.Date.class, dateTypeAdapter);
      }

      if (!deserializers.hasSpecificHandlerFor(Date.class)) {
          deserializers.register(Date.class, dateTypeAdapter);
      }
      if (!deserializers.hasSpecificHandlerFor(Timestamp.class)) {
          deserializers.register(Timestamp.class, dateTypeAdapter);
      }
      if (!deserializers.hasSpecificHandlerFor(java.sql.Date.class)) {
          deserializers.register(java.sql.Date.class, dateTypeAdapter);
      }
    }
....

Original comment by das...@gmail.com on 7 Feb 2011 at 12:09

GoogleCodeExporter commented 9 years ago
This issue was closed by revision r762.

Original comment by limpbizkit on 29 Mar 2011 at 9:36