Установите часовой пояс Джексона для десериализации даты - PullRequest
39 голосов
/ 26 сентября 2011

Я использую Джексона (через Spring MVC Annotations) для десериализации поля в java.util.Date из JSON. POST выглядит как - {"enrollDate":"2011-09-28T00:00:00.000Z"}, но когда объект создается Spring & Jackson, он устанавливает дату как "2011-09-27 20:00:00".

Как мне установить правильный часовой пояс в Джексоне? Или, если это не проблема, как мне отправить 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"}

Пружинный контроллер:

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

Ответы [ 7 ]

40 голосов
/ 29 декабря 2014

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

@JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd'T'HH:mm:ss.SSSZ", timezone="America/Phoenix")
private Date date;
15 голосов
/ 23 марта 2012

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

Не оказывает вредного влияния на тех, кто понимает часовой пояс-р

6 голосов
/ 24 февраля 2018

Вы пробовали это в своем приложении? Properties?

spring.jackson.time-zone= # Time zone used when formatting dates. For instance `America/Los_Angeles`
4 голосов
/ 14 февраля 2014

Я использую 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» в сообщении JSON я получаю «2014-02-13T08: 09: 09.859 + 0000», что, очевидно, неверно. У меня нет времени просматривать исходный код библиотеки Джексона, чтобы выяснить, почему это происходит, однако я обнаружил, что если я просто укажу предоставленный Джексоном класс ISO8601DateFormat для метода ObjectMapper.setDateFormat, дата будет правильной.

За исключением того, что это не переводит миллисекунды в тот формат, который мне нужен, поэтому я переклассифицировал класс ISO8601DateFormat и переопределил format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) метод. * * 1010

/**
 * 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;
  }
}
1 голос
/ 03 ноября 2017

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

ZonedDateTime

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

1 голос
/ 04 июня 2014

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

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

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

Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
cal.setTime(date);
System.out.println (cal);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...