【问题标题】:What is the easiest way to deserialize human readable time duration in Java?在 Java 中反序列化人类可读持续时间的最简单方法是什么?
【发布时间】:2018-09-07 22:11:03
【问题描述】:

我需要为一个项目设置可配置的超时时间,该项目从 YAML 文件中读取不同的配置。

我注意到java.time.Duration 有方法parse,Jackson 使用它来反序列化持续时间字符串。问题是它使用 ISO-8601 格式并期望持续时间具有PnDTnHnMn.nS 格式。虽然遵循标准是个好主意,但要求人们提供超时,因为PT10M 不是最佳选择,而10m 是首选。

我确实为持续时间字段编写了一个自定义反序列化器,但杰克逊默认无法处理这个似乎很奇怪。

使用 Jackson ObjectMapper 将人类友好的 10m5s1h 反序列化为 java.time.Duration 的最简单方法是什么?

【问题讨论】:

  • 仅供参考: 读取和解释像10m 这样的输入称为解析,而不是反序列化。
  • 看起来这些输入是非标准的,例如,我怎么知道m 表示分钟而不是月?我希望生成这些人类友好字符串的同一个库可以选择使用这种东西。
  • 我认为 Duration 甚至没有一个月选项
  • 我认为将timeout-minutes 放在配置中是最好的选择。

标签: java jackson deserialization duration jackson-modules


【解决方案1】:

反序列化人类友好的10m5s1h 的“最简单”方法可能是正则表达式和Java 代码的组合。

public static Duration parseHuman(String text) {
    Matcher m = Pattern.compile("\\s*(?:(\\d+)\\s*(?:hours?|hrs?|h))?" +
                                "\\s*(?:(\\d+)\\s*(?:minutes?|mins?|m))?" +
                                "\\s*(?:(\\d+)\\s*(?:seconds?|secs?|s))?" +
                                "\\s*", Pattern.CASE_INSENSITIVE)
                       .matcher(text);
    if (! m.matches())
        throw new IllegalArgumentException("Not valid duration: " + text);
    int hours = (m.start(1) == -1 ? 0 : Integer.parseInt(m.group(1)));
    int mins  = (m.start(2) == -1 ? 0 : Integer.parseInt(m.group(2)));
    int secs  = (m.start(3) == -1 ? 0 : Integer.parseInt(m.group(3)));
    return Duration.ofSeconds((hours * 60L + mins) * 60L + secs);
}

测试

System.out.println(parseHuman("1h"));
System.out.println(parseHuman("1 hour 200 minutes"));
System.out.println(parseHuman("3600 secs"));
System.out.println(parseHuman("2h3m4s"));

输出

PT1H
PT4H20M
PT1H
PT2H3M4S

【讨论】:

  • 感谢 Adreas,很好的解决方案。现在我只使用:Duration.parse(("PT" + text).toUpperCase()),但您的解决方案确实涵盖了更多案例并且以更好的方式失败。
猜你喜欢
  • 2010-12-29
  • 2015-06-10
  • 1970-01-01
  • 2021-10-24
  • 1970-01-01
  • 1970-01-01
  • 2023-03-30
  • 2012-03-31
  • 2010-11-19
相关资源
最近更新 更多