Формат OffsetDateTime JSON, позволяющий использовать шаблоны двух типов

#java #json #jackson

#java #json #джексон

Вопрос:

Я внедряю приложение в Spring Boot. Использование Джексона.

Можно ли в любом случае указать JsonFormat для анализа двух типов даты, например:

  • 2020-10-06T10:15:30 01:00
  • 2020-10-06T10:15:30

Мое текущее поле:

   @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss Z")
  private OffsetDateTime interval;
  

Должен ли я где-то указывать какой-то ObjectMapper в конфигурации?

Я извлекаю эту ошибку:

  com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.time.OffsetDateTime` from String "2020-10-06T10:15:30 01:00": Failed to deserialize java.time.OffsetDateTime: (java.time.format.DateTimeParseException) Text '2020-10-06T10:15:30 01:00' could not be parsed at index 10
  

С уважением

Комментарии:

1. В вашем шаблоне отсутствует разница T между датой и временем… Сделайте это "yyyy-MM-dd'T'HH:mm:ssZ" и повторите попытку. В java.time шаблоне даже должно быть "uuuu-MM-dd'T'HH:mm:ssxxx" , но я не знаю, сможет ли JPA справиться с этим.

2. Он работает для 2020-10-06T10:15:30 01:00, но не для 2020-10-06T10:15:30

3. В последнем вводе отсутствует смещение 01:00 , вы можете попытаться сделать его необязательным в pattern ( "yyyy-MM-dd'T'HH:mm:ss[Z]" ) , но я не думаю, что результат всегда будет действительным OffsetDateTime . Если вы обрабатываете String s таких разных форматов (важные элементы могут быть там или нет), вам придется использовать разные шаблоны. Вы не можете создать OffsetDateTime синтаксический анализ a String , который не имеет / указывает смещение.

4. @Ernesto Какое смещение должно interval иметь значение, если во входной строке не указано смещение часового пояса?

Ответ №1:

Вам нужно проанализировать, используя a DateTimeFormatter с дополнительным смещением зоны, поэтому вам нужен пользовательский JsonDeserializer :

 public class OffsetDateTimeOptionalZoneDeserializer extends StdScalarDeserializer<OffsetDateTime> {
    private static final DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
            .optionalStart()
            .appendOffsetId()
            .optionalEnd()
            .parseDefaulting(ChronoField.OFFSET_SECONDS, 0)
            .toFormatter();

    public OffsetDateTimeOptionalZoneDeserializer() { super(OffsetDateTime.class); }

    @Override
    public OffsetDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        return OffsetDateTime.parse(p.getText(), formatter);
    }
}
  

Тест

 public class Test {

    @JsonDeserialize(using = OffsetDateTimeOptionalZoneDeserializer.class)
    private OffsetDateTime interval;

    public static void main(String[] args) throws Exception {
        String json = "["  
                        "{ "interval": "2020-10-06T10:15:30 01:00" },"  
                        "{ "interval": "2020-10-06T10:15:30Z" },"  
                        "{ "interval": "2020-10-06T10:15:30" }"  
                      "]";
        
        ObjectMapper mapper = new ObjectMapper();
        Test[] tests = mapper.readValue(json, Test[].class);
        for (Test t : tests)
            System.out.println(t.interval);
    }
}
  

Вывод

 2020-10-06T10:15:30 01:00
2020-10-06T10:15:30Z
2020-10-06T10:15:30Z