【问题标题】:is it possible to make certain part of the JsonFormat datetime optional?是否可以将 JsonFormat 日期时间的某些部分设为可选?
【发布时间】:2020-02-13 21:23:50
【问题描述】:

我有一个用秒部分定义的字段,(即:“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”

我正在考虑类似的事情(但这不起作用......): "yyyy-MM-dd'T'HH:mm[:ss] z"

谢谢。

【问题讨论】:

  • 你需要使用Date类吗?该课程设计不良且早已过时。我会从java.time, the modern Java date and time API 尝试ZonedDateTime。您是否需要依赖三个字母的时区缩写? EST 是模棱两可的,所以我认为你不能确定你得到了什么。

标签: java json date datetime format


【解决方案1】:

我得到了答案。

  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);
        }
    }
}
} 

【讨论】:

  • 感谢您回答您自己的问题。 SimpleDateFormat 类是出了名的麻烦和过时。而且它不是线程安全的,所以如果你仍然想使用,不要将它存储到静态字段中。
【解决方案2】:

由于SimpleDateFormat 类出了名的麻烦、过时且不是线程安全的,我想我会向您展示如何使用现代 Java 日期和时间 API java.time 来解决您的任务。现在我假设你不能改变你的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 相反),因此即使在多个线程中使用,也可以只拥有一个静态实例。 DateTimeFormatter.parse() 如果无法解析字符串,则会抛出运行时异常(未经检查的异常),所以我没有找到任何理由在我们自己的代码中明确说明。

如果您可以进行以下任何更改,它仍然会改善问题:

  • 让您的日期时间字符串的来源使用 ISO 8601 格式,例如 2020-02-13T16:02:11-05:00。他们现在使用的格式是 ISO 8601 和非 ISO 的特殊组合,因此您和他们实际上既没有获得标准的优势,也没有获得更易于阅读的格式的全部潜在优势。 ISO 8601 的格式化程序内置在 java.time 中,因此使用该标准可以避免我们自己定义任何格式化程序。在 ISO 8601 中,秒 是可选的,因此它们仍然可以发送带或不带秒的字符串。
  • 扔掉Date 类。它设计得很糟糕,而且已经过时了。使用 Instant 或 java.time 中的其他类并保存我在代码中所做的转换。

链接

【讨论】:

    猜你喜欢
    • 2023-03-13
    • 1970-01-01
    • 2015-03-09
    • 2016-11-10
    • 2020-07-31
    • 1970-01-01
    • 2015-10-10
    • 2020-06-30
    相关资源
    最近更新 更多