开发者

Invalid json representation of date

My code:

import net.sf.json.JSONObject;
import net.sf.json.JSONSerializer;
...
public void testDateSerializer() {
  final Date date = new Date();
  log.info("Today's date: " + date + " and date.getTime()=" + date.getTime());
  final JSONObject jsonObjectForDate = (JSONObject) JSONSerializer.toJSON(date);
  log.info("Same date expressed in json: " + jsonObjectForDate.toString());
}

The output:

INFO - 2011-08-13 22:12:04,938 - TestJsonConversion.testDateSerializer(52) | Today's date: Sat Aug 13 22:12:04 EDT 2011 and date.getTime()=1313287924927
INFO - 2011-08-13 22:12:05,216 - TestJsonConversion.testDateSerializer(55) | Same date expressed in json: {"date":13,"day":6,"hours":22,"minutes":12,"month":7,"seconds":4,"time":1313287924927,"tim开发者_Python百科ezoneOffset":240,"year":111}

My questions:

  • Why year=111. We are still in 2011 unless I missed something!
  • I am on US ETD, so offset is -4 hours, not +240, which, even expressed in minutes is still wrong regarding the sign of the offset.

So what am I doing wrong? Is this a bug in the library? If so, what library should I use to accomplish the same conversion?

Thank you


Joda Time is indeed the way to go. However, if you are stuck with java.util.Date for whatever reason, you could customize the serialization this way:

   JsonConfig config = new JsonConfig();
   config.registerJsonValueProcessor(
        Class.forName("java.util.Date"), 
        new NiceDateJsonBeanProcessor());
   final JSONObject jsonObjectForDate = JSONSerializer.toJSON(object, jsonConfig)

Where NiceDateJsonBeanProcessor is how you define what you want your java.util.Date object to be serialized as. In my case, I was happy with unix time, so:

public static class NiceDateJsonBeanProcessor implements JsonValueProcessor {
    @Override
    public Object processArrayValue(Object value, JsonConfig jsonConfig) {
        return process(value, jsonConfig);
    }
    @Override
    public Object processObjectValue(String key, Object value, JsonConfig jsonConfig) {
        return process(value, jsonConfig);
    }
    private Object process(Object value, JsonConfig jsonConfig) {
        if (value instanceof java.util.Date) {
            java.util.Date d = (java.util.Date) value;
            return d.getTime();
        }
        return null;
    }
}


Actually this behavior is completely expected, believe it or not.

You are using the class java.util.Date. This class has mostly a bunch of deprecated methods. See the documentation here:

http://download.oracle.com/javase/6/docs/api/java/util/Date.html

Now your JSON serializer is just going to make a JSON string out of the getters in your Java object. Take a look at the getters in the java.util.Date class. Most are deprecated and you can see why. The year is relative to 1900! The time zone offset is in minutes backwards.

To make your application work the way you would expect, check out the deprecation warnings for Date which tell you to use GregorianCalendar. However, I recommend using JodaTime. A little learning curve, but this is so worth it.


It might help to look at the source of JSONObject here

Basically, it treats your passed-in Date object as a Java Bean. So, it iterates through reflection, all the "get*" methods in your date object and that's what you see in your JSONObject.

All the java.util.Date object's get methods are deprecated and you see weirdness, like the year being 111 instead of 2011.

If you want to pass date objects via JSON, you might consider passing them as String objects formatted in a specific way OR use Calendar.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜