Можно ли сделать определенную часть даты и времени JsonFormat необязательной? - PullRequest
0 голосов
/ 14 февраля 2020

У меня есть поле, которое определяется частью секунд (то есть: "ss") следующим образом

@JsonProperty("date")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss z")
private Date date;

Можно ли сделать часть секунд необязательной? так что обе следующие строки даты будут работать:

  • «2020-02-13T16: 02: 11 EST» будет проанализирован на «Thu Feb 13 16:02:11 EST 2020»
  • «2020-02-13T16: 02 EST» будет проанализирован на «Thu Feb 13 16:02 EST 2020»

Я думаю о чем-то подобном (хотя это не работает ... ): "гггг-мм-дд'т'ч: мм [: сс] z"

спасибо.

Ответы [ 2 ]

0 голосов
/ 19 февраля 2020

Поскольку класс SimpleDateFormat общеизвестно проблематичен и давно устарел, а также не поточнобезопасен, я подумал, что покажу вам, как решить вашу задачу с помощью java .time, современного Java API даты и времени , На данный момент я предполагаю, что вы не можете изменить тип вашего поля date, оно должно быть Date, а также что вы не можете изменить формат / с. Я переписал класс из вашего собственного ответа следующим образом:

public class DateDeserializer extends StdDeserializer<Date> {

    private static final DateTimeFormatter formatter
            = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm[:ss] z", Locale.ENGLISH);

    public DateDeserializer() {
        this(null);
    }

    public DateDeserializer(Class<?> vc) {
        super(vc);
    }

    @Override
    public Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        String dateString = p.getText();
        if (dateString.isEmpty()) {
            //handle empty strings however you want,
            //but I am setting the Date objects null
            return null;
        }

        Instant parsedInstant = formatter.parse(dateString, Instant::from);
        return Date.from(parsedInstant);
    }
} 

В строке шаблона формата я использую квадратные скобки, [], около дополнительных секунд минуты. DateTimeFormatter является поточно-ориентированным (напротив SimpleDateFormat), поэтому безопасно иметь только один экземпляр stati c, даже если он используется из нескольких потоков. DateTimeFormatter.parse() выдает исключение времени выполнения (непроверенное исключение), если он не может проанализировать строку, поэтому я не нашел причин, чтобы сделать это явным в нашем собственном коде.

Если вы могли бы внести любое из следующих изменений , это могло бы улучшить положение вещей:

  • Обучите источник ваших строк даты и времени использовать формат ISO 8601, например 2020-02-13T16:02:11-05:00. Используемый ими в настоящее время формат представляет собой своеобразное сочетание ISO 8601 и не-ISO, поэтому вы и они на самом деле не получаете ни преимущества стандарта, ни полных потенциальных преимуществ более удобочитаемого формата. Форматеры для ISO 8601 встроены в java .time, поэтому использование стандарта избавит нас от необходимости самостоятельно определять любой форматтер. И секунды являются необязательными в ISO 8601, поэтому они могут отправлять строки с секундами и без.
  • Выбрасывать класс Date. Он плохо спроектирован и давно устарел. Используйте Instant или другой класс из java .time и сохраните преобразование, которое я делаю в коде.

Ссылки

0 голосов
/ 18 февраля 2020

Я получил ответ.

  1. добавьте специальный класс десериализатора 'DateDeserializer.class'
  2. DateDeserializer.class реализует оба шаблона со второй частью и без нее.

пример кода привязан:

@JsonDeserialize(using = DateDeserializer.class)
@JsonProperty("date")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss z")




public class DateDeserializer extends StdDeserializer<Date> {

private static final SimpleDateFormat withSeconds = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss z");
private static final SimpleDateFormat withoutSeconds = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm z");

public DateDeserializer() {
    this(null);
}

public DateDeserializer(Class<?> vc) {
    super(vc);
}

@Override
public Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
    String dateString = p.getText();
    if (dateString.isEmpty()) {
        //handle empty strings however you want,
        //but I am setting the Date objects null
        return null;
    }

    try {
        return withSeconds.parse(dateString);
    } catch (ParseException e) {
        try {
            return withoutSeconds.parse(dateString);
        } catch (ParseException e1) {
            throw new RuntimeException("Unable to parse date", e1);
        }
    }
}
} 
...