简体   繁体   中英

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,"timezoneOffset":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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM