2011-09-26 11 views
29

Używam Jackson (poprzez Spring MVC Adnotacje) do deserializacji pola do java.util.Date z JSON. POST wygląda tak: - {"enrollDate":"2011-09-28T00:00:00.000Z"}, ale kiedy Obiekt jest tworzony przez Spring & Jackson, ustawia datę jako "2011-09-27 20:00:00".Ustaw zmienną Jackson Timezone dla deserializacji daty

Jak ustawić właściwą strefę czasową w Jackson? A jeśli to nie jest problem, w jaki sposób wysłać EST z komunikatu JSON?

JavaScript/jQuery:

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


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

}); 

JSON Wiadomość:

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

Wiosna Kontroler:

@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

W której strefie czasowej jesteś? Jeśli jesteś 4h na zachód od UTC, te 2 znaczki są równoważne. – fvu

+0

Jestem w EST. Dlaczego więc Jackson przyjmuje, że nadchodzący czas, który wysłałem, to GMT? Czy powinienem zmienić javascript, aby inaczej opublikować datę, czy zmienić ustawienie z Jacksonem? –

+3

Z na końcu znacznika czasu jest skrótem +00: 00, inaczej czas Zulu, czyli UTC/GMT. – fvu

Odpowiedz

1

Twój obiekt data jest chyba ok, skoro wysłał datę zakodowane w formacie ISO ze strefy czasowej GMT i jesteś w EST podczas drukowania daty.

Należy zauważyć, że obiekty Date wykonują translację strefy czasowej w momencie, gdy są one wydrukowane. Można sprawdzić, czy obiekt date jest poprawny z:

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

Jeśli naprawdę chcesz Jackson zwraca datę z innej strefy czasowej niż UTC (a ja mam kilka dobrych argumentów za tym, zwłaszcza, gdy niektórzy klienci po prostu nie „t dostać część strefy czasowej), a następnie zwykle zrobić:

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 

ma on żadnych negatywnych skutków dla tych, którzy rozumieją strefy czasowej-p

+11

Wygląda na to, że mapper.getSerializationConfig(). SetDateFormat (dateFormat) jest przestarzały, a nowy sposób to zrobić to mapper.setDateFormat (dateFormat) – Tim

3

Używam Jackson 1.9.7 i stwierdziliśmy, że w następujący sposób nie rozwiązuje mojej serializacji/des Kwestia stref czasowych erialization:

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

Zamiast "2014-02-13T20: 09: 09.859Z" otrzymuję "2014-02-13T08: 09: 09,859 + 0000" w komunikacie JSON, który jest oczywiście błędne. Nie mam czasu, aby przejrzeć kod źródłowy biblioteki Jacksona, aby dowiedzieć się, dlaczego tak się dzieje, jednak odkryłem, że jeśli podam tylko podaną przez Jacksona klasę ISO8601DateFormat do metody ObjectMapper.setDateFormat, data jest prawidłowa.

Poza tym nie stawia milisekundy w formacie, który jest to, co chcę, więc sub-klasyfikowane klasę ISO8601DateFormat i overrode metodę 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

Dane wyjściowe są dokładnie zgodne z podanymi przez SimpleDateFormat. Per [SimpleDateFormat Javadoc] (http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html): hh wypisuje 12-godzinny czas, kk wypisze 24-krotnie, a Z - odsunięcie strefy czasowej . Myślę, że chciałeś mieć format daty jawnej "yyyy-MM-dd'T'kk: mm: ss.SSS'Z''. – kaliatech

+0

Format daty był drobnym problemem, głównym problemem dla mnie było to, że rzeczywiste wartości daty wypluwane przez ObjectMapper były nieprawidłowe. Przyjrzyj się dokładnie przykładowi, który podałem, dane wyjściowe były w rzeczywistości 12 godzin od tego, co było oczekiwane, czyli zamiast "2014-02-13T20: 09: 09.859Z" dostałem "2014-02-13T08: 09: 09.859 +0000 " – whitestryder

+0

08:09:09 w _12_ godzinie (przy braku wskaźnika am/pm) jest równoważne 20:09:09 w _24_ godzinie. – kaliatech

1

Miałem ten sam problem z deserializacją kalendarza, rozwiązano rozszerzenie CalendarDeserializer.
Zmusza UTC strefy czasowej
wkleić kod, jeżeli ktoś to potrzebne:

@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 w klasie modelu tylko opisywanie tej dziedzinie:

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

w Jackson 2+, można również użyć adnotacji @JsonFormat:

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

@JsonFormat (shape = JsonFormat.Shape.STRING, pattern = "rrrr-MM-dd'T'HH: mm: ss.SSSZ", timezone = "US/Arizona") –

0

Właśnie weszła w ten temat i wreszcie zrozumiał, że LocalDateTime nie ma żadnych informacji o strefie czasowej. Jeśli otrzymał datę ciąg ze strefy czasowej, trzeba to wykorzystać jako typ:

ZonedDateTime

Sprawdź to link

0

Czy próbowałeś to w twoich application.properties?

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