我如何使用杰克逊JSON映射与Java 8 LocalDateTime?
jsonmappingexception:不能实例化类型[简单类型,java.time类]的值。LocalDateTime] from JSON字符串;没有单字符串构造函数/工厂方法(通过引用链:MyDTO["field1"]->SubDTO["date"])
我如何使用杰克逊JSON映射与Java 8 LocalDateTime?
jsonmappingexception:不能实例化类型[简单类型,java.time类]的值。LocalDateTime] from JSON字符串;没有单字符串构造函数/工厂方法(通过引用链:MyDTO["field1"]->SubDTO["date"])
当前回答
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-parameter-names</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
添加这些依赖项并启用这些模块。这应该会有帮助
private static final ObjectMapper mapper = new ObjectMapper().findAndRegisterModules();
其他回答
如果你考虑使用fastjson,你可以解决你的问题,注意版本
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.56</version>
</dependency>
不幸的是,这里提出的解决方案在我的环境中不起作用。 但说实话,使用java8时间对象作为dto毕竟不是一个很好的主意。
我建议创建自定义dto,不要依赖于不稳定的库,它可能在下次jdk发布后崩溃。这种方法也符合反腐败层和适配器模式的良好实践。
下面是DTO的示例:
public class ReportDTO implements Serializable {
private YearMonthDTO yearMonth;
public YearMonthDTO getYearMonth() {
return yearMonth;
}
public void setYearMonth(final YearMonthDTO yearMonth) {
this.yearMonth = yearMonth;
}
public void fromYearMonth(final YearMonth yearMonth) {
this.yearMonth = new YearMonthDTO(yearMonth.getYear(),
yearMonth.getMonthValue());
}
}
public static class YearMonthDTO {
private int year;
private int monthValue;
public YearMonthDTO() {
}
public YearMonthDTO(int year, int monthValue) {
this.year = year;
this.monthValue = monthValue;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getMonthValue() {
return monthValue;
}
public void setMonthValue(int monthValue) {
this.monthValue = monthValue;
}
}
当然,这取决于你的情况,以及你要用这个解决方案做的工作量。与任何模式一样,此解决方案并不适用于所有情况。
无论如何,目前最好的答案似乎不再适用了。我没有尝试其他解决方案,但我决定在这个简单的案例中不依赖任何库。
这个maven依赖将解决你的问题:
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.13.4</version>
</dependency>
我一直在挣扎的一件事是,在反序列化期间,ZonedDateTime时区被更改为GMT。 结果,Jackson默认用上下文中的一个替换它。 要保留区域1,必须禁用此“功能”
Jackson2ObjectMapperBuilder.json()
.featuresToDisable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE)
如果有人在使用SpringBoot时遇到问题,这里是我在不添加新的依赖项的情况下修复问题的方法。
在Spring 2.1.3中,Jackson期望在此yyyy-MM-dd HH:mm:ss中出现日期字符串2019-05-21T07:37:11.000。在LocalDateTime中反序列化SSS格式。确保日期字符串用T分隔日期和时间,而不是用空格。秒(ss)和毫秒(SSS)可以省略。
@JsonProperty("last_charge_date")
public LocalDateTime lastChargeDate;
这里不需要使用自定义序列化器/反序列化器。使用jackson-modules-java8的datetime模块:
数据类型模块,使Jackson识别Java 8日期和时间API数据类型(JSR-310)。
这个模块增加了对很多类的支持:
持续时间 即时 LocalDateTime LocalDate 本地时间 MonthDay OffsetDateTime OffsetTime 期 一年 YearMonth ZonedDateTime ZoneId ZoneOffset