2011-09-26 90 views
29

我使用Jackson(通過Spring MVC Annotations)將字段反序列化爲來自JSON的java.util.Date。 POST看起來像 - {"enrollDate":"2011-09-28T00:00:00.000Z"},但是當對象由Spring & Jackson創建時,它將日期設置爲"2011-09-27 20:00:00"設置日期反序列化的傑克遜時區

如何在傑克遜設置適當的時區? 或者如果這不是問題,我該如何從JSON消息發送EST?

的Javascript/jQuery的:

var personDataView = { enrollDate : new Date($("#enrollDate").val()), 
         //...other members 
         }; 


$.postJSON('/some/path/', personDataView, function(data){ 
    //... handle the response here 

}); 

JSON消息:

{"enrollDate":"2011-09-28T00:00:00.000Z"}

彈簧控制器:

@RequestMapping(value="/", method=RequestMethod.POST) 
public @ResponseBody String saveProfile(@RequestBody personDataView persondataView, HttpServletRequest request) 
{ 
     //...dataView has a java.util.Date enrollDate field 
     //...other code 
} 
+2

在什麼時區是你嗎?如果你在UTC以西4h這兩個郵票是相同的。 – fvu

+0

我在美國東部時間。那麼爲什麼傑克遜假設我發送的時間是GMT?我應該改變我的javascript以不同的方式發佈日期,或者更改Jackson的設置? –

+3

時間戳結尾的Z是速記+00:00又名祖魯時間aka UTC/GMT。 – fvu

回答

1

你的約會對象可能是好的,因爲你給你的約會與GMT時區ISO格式編碼的,你在EST時您打印日期。

請注意,日期對象在打印時執行時區轉換。您可以檢查您的date對象是正確的有:

Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); 
cal.setTime(date); 
System.out.println (cal); 
14

如果你真的想傑克遜返回的日期比UTC另一個時區(而我自己有幾個很好的理由,尤其是當一些客戶只是不「T得到了時區的一部分),那麼我通常做:

ObjectMapper mapper = new ObjectMapper(); 
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); 
dateFormat.setTimeZone(TimeZone.getTimeZone("CET")); 
mapper.getSerializationConfig().setDateFormat(dateFormat); 
// ... etc 

這對那些瞭解時區-p

+11

似乎mapper.getSerializationConfig()。setDateFormat(日期格式)現在已被棄用,新的​​方式來做到這一點是mapper.setDateFormat(日期格式) – Tim

3

我使用傑克遜1.9.7並沒有不利的影響,我發現,這樣做以下並沒有解決我的序列化/ des erialization時區的問題:

DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSSZ"); 
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); 
objectMapper.setDateFormat(dateFormat); 

而不是 「2014-02-13T20:09:09.859Z」 我知道 「2014-02-13T08:09:09.859 + 0000」 的JSON消息是顯然是不正確。我沒有時間通過​​Jackson庫源代碼來弄清楚爲什麼發生這種情況,但是我發現如果我只是指定Jackson爲ObjectMapper.setDateFormat方法提供了ISO8601DateFormat類,那麼日期是正確的。

除了這不把毫秒的格式,這是我想要的所以我分類ISO8601DateFormat類和overrode的方法format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) 方法。

/** 
* Provides a ISO8601 date format implementation that includes milliseconds 
* 
*/ 
public class ISO8601DateFormatWithMillis extends ISO8601DateFormat { 

    /** 
    * For serialization 
    */ 
    private static final long serialVersionUID = 2672976499021731672L; 


    @Override 
    public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) 
    { 
     String value = ISO8601Utils.format(date, true); 
     toAppendTo.append(value); 
     return toAppendTo; 
    } 
} 
+0

輸出正是你給它SimpleDateFormat的匹配。每[SimpleDateFormat的Javadoc中](http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html):HH輸出端12小時的時間,KK輸出24的時間,和Z輸出時區偏移。我想你想要明確的日期格式爲'yyyy-MM-dd'T'kk:mm:ss.SSS'Z''。 – kaliatech

+0

日期的格式是一個小問題,對我來說主要問題是ObjectMapper吐出的實際日期值不正確。在我給的例子仔細看,日產量實際上與預期12小時關閉,也就是說,不是,「2014-02-13T20:09:09.859Z」我「2014-02-13T08:09:09.859 0000" – whitestryder

+0

在_12_ 8點09分09秒小時時間(與AM/PM指示器缺失)等效於在_24_小時時間20點09分09秒。 – kaliatech

1

我曾與日曆反序列化同樣的問題,解決了延長CalendarDeserializer。
它迫使UTC時區
我貼的代碼,如果有人需要它:

@JacksonStdImpl 
public class UtcCalendarDeserializer extends CalendarDeserializer { 

    TimeZone TZ_UTC = TimeZone.getTimeZone("UTC"); 

    @Override 
    public Calendar deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { 
     JsonToken t = jp.getCurrentToken(); 
     if (t == JsonToken.VALUE_NUMBER_INT) { 
      Calendar cal = Calendar.getInstance(TZ_UTC); 
      cal.clear(); 
      cal.setTimeInMillis(jp.getLongValue()); 

      return cal; 
     } 

     return super.deserialize(jp, ctxt); 
    } 
} 
在JSON模型類

只是註釋字段:

@JsonDeserialize(using = UtcCalendarDeserializer.class) 
private Calendar myCalendar; 
23

在傑克遜2+,你也可以使用@JsonFormat註釋:

@JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd'T'HH:mm:ss.SSSZ", timezone="America/Phoenix") 
private Date date; 
+1

@JsonFormat(形狀= JsonFormat.Shape.STRING,圖案= 「YYYY-MM-dd'T'HH:MM:ss.SSSZ」,時區= 「US /亞利桑那」) –

0

剛進入這個問題,最後意識到LocalDateTime沒有任何時區信息。如果您收到的日期字符串時區的信息,你需要使用這個作爲類型:

ZonedDateTime

入住這link

0

有你在application.properties試過嗎?

spring.jackson.time-zone= # Time zone used when formatting dates. For instance `America/Los_Angeles`