我有一个包含 ISO8601 持续时间字符串(P3Y6M4DT12H30M5S)的字符串值。 如何使用 Jackson 将其反序列化为 Duration 和 period 对象? 我知道 Duration 接受天、小时、分钟、秒和 Period 年和月。
org.threeten.extra.PeriodDuration.parse( "P3Y6M4DT12H30M5S" ) ;
Period
代表年、月、日规模的时间跨度。Duration
表示以小时为单位的时间跨度,
分钟、秒和纳秒。注意事项:将这两个概念合并为一个,如示例输入字符串所示,在实践中很少有意义。
PeriodDuration
班级但是,如果您坚持使用这些值,则有一个类可以实现。将 ThreeTen-Extra 库添加到您的项目中。然后您就可以访问
PeriodDuration
课程。
无需定义格式化模式。您的输入符合 ISO 8601 标准。 java.time 类在解析/生成文本时默认使用标准格式。
org.threeten.extra.PeriodDuration pd = PeriodDuration.parse( "P3Y6M4DT12H30M5S" ) ;
以标准 ISO 8601 格式生成文本。
String output = pd.toString() ;
您会在该类中找到一些方便的方法,用于构造、标准化、数学(加法、减法、求反)等。
至于杰克逊,我不是用户。我不知道如何在 Jackson 中使用第三方类作为自动格式化程序。
我不想使用外部依赖来使用如此简单的方法,所以我自己实现了它。
我创建了 PeriodDuration 类,其中包含周期和持续时间字段。
接下来,我创建了扩展 StdDeserializer 的反序列化器,并用 @JsonDeserializer(using = "nameOfMyCustomDeserializer.class)
注释了
PeriodDuration类。该解串器将 iso8601 持续时间字符串拆分为两个字符串,即“T”之前和“T”之后。如果周期部分为空,则设置Period.ZERO,但如果持续时间部分为空,则设置Duration.ZERO。
将 com.fasterxml.jackson.datatype.jsr310.JavaTimeModule 添加到您的 JsonMapper/ObjectMapper - 请参阅 https://github.com/FasterXML/jackson-modules-java8。
对于序列化,您需要禁用 SerializationFeature.WRITE_DATES_AS_TIMESTAMPS - 默认情况下处于启用状态。禁用时,持续时间输出为 ISO-8601 格式(例如 PT12H 为 12 小时)。
我使用的 API 可在月份(期间)和天(持续时间)内返回 ISO8601。这是我在客户端代码中所做的:
public class ObjectMapperFactory {
private ObjectMapper buildMapper() {
return JsonMapper.builder()
.addModule(new JavaTimeModule())
.addModule(new SimpleModule().addDeserializer(TemporalAmount.class, new TemporalAmountDeserializer()))
.build();
}
public static class TemporalAmountDeserializer extends JsonDeserializer<TemporalAmount> {
@Override
public TemporalAmount deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
try {
var durationDeserializer = ctxt.findRootValueDeserializer(ctxt.constructType(Period.class));
return (Period) durationDeserializer.deserialize(p, ctxt);
} catch (Exception e) {
try {
var periodDeserializer = ctxt.findRootValueDeserializer(ctxt.constructType(Duration.class));
return (Duration) periodDeserializer.deserialize(p, ctxt);
} catch (Exception ex) {
throw JsonMappingException.from(p, "Could not deserialize as either Duration or Period", ex);
}
}
}
}
}