Ответ 1
В Jackson 2+ вы также можете использовать аннотацию @JsonFormat:
@JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd'T'HH:mm:ss.SSSZ", timezone="America/Phoenix")
private Date date;
Я использую Jackson (через Spring MVC Annotations) для десериализации поля в java.util.Date
от JSON. POST выглядит как {"enrollDate":"2011-09-28T00:00:00.000Z"}
, но когда объект создается Spring и Jackson, он устанавливает дату как "2011-09-27 20:00:00"
.
Как установить правильный часовой пояс в Jackson? Или, если это не проблема, как отправить EST из сообщения JSON?
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"}
Spring Контроллер:
@RequestMapping(value="/", method=RequestMethod.POST)
public @ResponseBody String saveProfile(@RequestBody personDataView persondataView, HttpServletRequest request)
{
//...dataView has a java.util.Date enrollDate field
//...other code
}
В Jackson 2+ вы также можете использовать аннотацию @JsonFormat:
@JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd'T'HH:mm:ss.SSSZ", timezone="America/Phoenix")
private Date date;
Если вы действительно хотите, чтобы Джексон вернул дату с другим часовым поясом, чем UTC (и у меня есть несколько хороших аргументов для этого, особенно когда некоторые клиенты просто не получают часть часового пояса), то я обычно делаю:
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
Я использую Jackson 1.9.7, и я обнаружил, что выполнение следующего не решает проблему с часовым поясом сериализации/десериализации:
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, предоставляемый ISO8601DateFormat
методу ObjectMapper.setDateFormat
, дата верна.
Кроме того, это не помещает миллисекунды в формат, который я хочу, поэтому я подклассифицировал класс ISO8601DateFormat
и переопределил 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;
}
}
Ваш объект даты, вероятно, одобрен, поскольку вы отправили свою дату, закодированную в формате ISO, с часовым поясом GMT, и вы находитесь в EST, когда вы печатаете дату.
Обратите внимание, что объекты Date выполняют трансляцию часового пояса в момент их печати. Вы можете проверить, соответствует ли ваш объект date
правилом:
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
cal.setTime(date);
System.out.println (cal);
У меня была такая же проблема с десериализацией календаря, что и было решено расширить 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;
Просто вошел в эту проблему и, наконец, понял, что LocalDateTime не имеет информации о часовом поясе. Если вы получили строку даты с информацией о часовом поясе, вам нужно использовать ее как тип:
ZonedDateTime
Проверьте ссылку