Jackson解析json字符串时报错:Cannot construct instance of `java.time.OffsetDateTime`的解决方案

当使用Jackson解析json字符串时遇到'Cannot construct instance of `java.time.OffsetDateTime`'的错误,原因是Jackson缺少对`OffsetDateTime`的解析支持。解决方法是在Jackson的ObjectMapper中注册一个模块以支持此类。注册模块后,Jackson可以正确解析`OffsetDateTime`以及其他Java 8的时间日期类型。通过一个简单的测试用例验证了解决方案的有效性。

Jackson解析json字符串时报错:Cannot construct instance of java.time.OffsetDateTime的解决方案

首先贴出报错信息:

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `java.time.OffsetDateTime` (no Creators, like default construct, exist): no String-argument constructor/factory method to deserialize from String value ('2018-01-01T12:05:14Z')
 at [Source: (String)"{"header":{"id":"7fdf40b1-5d98-4d83-9aaa-e6e7422c9f44",...,"creation_date_time":"2018-01-01T12:05:14Z"}"; line: 1, column: 77] (through reference chain: org.openmhealth.schema.domain.omh.DataPoint["header"]->org.openmhealth.schema.domain.omh.DataPointHeader["creation_date_time"])

简单看一下报错的信息大概就是Jackson在构建一个java.time.OffsetDateTime的实体时失败了,没有这样的一个构造器。也就是说对于这样一个字段2018-01-01T12:05:14Z不能将其还原成java.time.OffsetDateTime的一个对象。

了解出错的原因之后,我们再来看看如何将这个问题解决。

查阅资料后了解到,其实com.fasterxml.jackson.datatype: jackson-datatype-jsr310这个库提供了java.time.OffsetDateTime的解析支持,并且实现解析的方法也很简单,只需要对Jackson的ObjectMapper对象注册一个JavaTimeModule()就好了。

具体代码如下:

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());

好了,这样你的Jackson就能解析java.time.OffsetDateTime类型的字符串了。
除此之外,jackson-datatype-jsr310还支持以下几种数据类型:

  • Duration
  • Instant
  • LocalDateTime
  • LocalDate
  • LocalTime
  • MonthDay
  • OffsetDateTime
  • OffsetTime
  • Period
  • Year
  • YearMonth
  • ZonedDateTime
  • ZoneId
  • ZoneOffset

简单实验:

测试代码如下:(测试代码都略去了import部分,只包含程序主体)

Order类:

public class Order {
    private OffsetDateTime orderTime;
    private Long id;

    public OffsetDateTime getOrderTime() {
        return orderTime;
    }

    public void setOrderTime(OffsetDateTime orderTime) {
        this.orderTime = orderTime;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Override
    public String toString() {
        return "Order{" +
                "orderTime=" + orderTime +
                ", id=" + id +
                '}';
    }
}

JsonParser定义如下:

public class JsonParser {

    public void parseJson() throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        String jsonString = "[{\"orderTime\":\"2018-01-01T12:05:14Z\", \"id\":201801011205}]";
        JavaType type = TypeFactory.defaultInstance().constructType(Order.class);
        Order order = objectMapper.readValue(jsonString, type);
        System.out.println("解析json字符串之后得到的是: "+order.toString());
    }

}

json可视化工具

测试:

JsonParser jsonParser = new JsonParser();
jsonParser.parseJson();

程序报错,报错信息即为无法正常构建。

JsonParser做少许改造,使其能够正常解析java.time.OffsetDateTime的字符串。

public class JsonParser {
    
    public void parseJson() throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        //下面这行代码使得objectMapper支持解析java.time.OffsetDateTime
        objectMapper.registerModule(new JavaTimeModule());
        String jsonString = "[{\"orderTime\":\"2018-01-01T12:05:14Z\", \"id\":201801011205}]";
        JavaType type = TypeFactory.defaultInstance().constructType(Order.class);
        Order order = objectMapper.readValue(jsonString, type);
        System.out.println("解析json字符串之后得到的是: "+order.toString());
    }
}

运行结果如下:

解析json字符串之后得到的是: Order{orderTime=2018-01-01T12:05:14Z, id=201801011205}

Jackson解析java.time.OffsetDateTime成功!



参考资料:
serialize/deserialize java 8 java.time with Jackson JSON mapper

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值