New issue 230 by tradefields.analytics: GsonBuilder setDateFormat ignored
http://code.google.com/p/google-gson/issues/detail?id=230
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
It still happens in version 1.6 when the object is within a collection.
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();
That woule be cool to fix that in 1.7!
This should be a higher priority defect since working with dates is very
common. Hope this will be fixed as soon as possible.
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
Object obj = f.get(parent);
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".
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.
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);
}
}
....
Comment #9 on issue 230 by limpbiz...@gmail.com: GsonBuilder setDateFormat
ignored
http://code.google.com/p/google-gson/issues/detail?id=230
This issue was closed by revision r762.