Подтвердить что ты не робот

Установите часовой пояс Jackson для десериализации даты

Я использую 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
}
4b9b3361

Ответ 1

В Jackson 2+ вы также можете использовать аннотацию @JsonFormat:

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

Ответ 2

Если вы действительно хотите, чтобы Джексон вернул дату с другим часовым поясом, чем 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

Ответ 3

Я использую 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;
  }
}

Ответ 4

Ваш объект даты, вероятно, одобрен, поскольку вы отправили свою дату, закодированную в формате ISO, с часовым поясом GMT, и вы находитесь в EST, когда вы печатаете дату.

Обратите внимание, что объекты Date выполняют трансляцию часового пояса в момент их печати. Вы можете проверить, соответствует ли ваш объект date правилом:

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

Ответ 5

У меня была такая же проблема с десериализацией календаря, что и было решено расширить 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;

Ответ 6

Просто вошел в эту проблему и, наконец, понял, что LocalDateTime не имеет информации о часовом поясе. Если вы получили строку даты с информацией о часовом поясе, вам нужно использовать ее как тип:

ZonedDateTime

Проверьте ссылку