【问题标题】:Cannot deserialize value of type `java.time.Instant` - jackson无法反序列化“java.time.Instant”类型的值 - 杰克逊
【发布时间】:2020-06-18 12:11:56
【问题描述】:

有这样的课

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
public final class ActiveRecoveryProcess {

    private UUID recoveryId;
    private Instant startedAt;
}

我收到com.fasterxml.jackson.databind.exc.InvalidFormatException 和消息Cannot deserialize value of typejava.time.Instantfrom String "2020-02-22T16:37:23": Failed to deserialize java.time.Instant: (java.time.format.DateTimeParseException) Text '2020-02-22T16:37:23' could not be parsed at index 19

JSON 输入

{"startedAt": "2020-02-22T16:37:23", "recoveryId": "6f6ee3e5-51c7-496a-b845-1c647a64021e"}

杰克逊配置

    @Autowired
    void configureObjectMapper(final ObjectMapper mapper) {
        mapper.registerModule(new ParameterNamesModule())
                .registerModule(new Jdk8Module())
                .registerModule(new JavaTimeModule());
        mapper.findAndRegisterModules();
    }

编辑

JSON 是从 postgres 生成的

jsonb_build_object(
                        'recoveryId', r.recovery_id,
                        'startedAt', r.started_at
)

r.started_at 是 TIMESTAMP。

【问题讨论】:

  • Instant 正在整个项目中使用。为什么我应该考虑使用LocalDateTime 而不是Instant
  • 如果传入的数据只是说2020-02-22T16:37:23,而最后没有Z,你怎么知道确定时间是UTC?也许使用LocalDateTime 更适合这种没有时区的时间值。
  • 我编辑了我的帖子 - JSON 是从 Postgres 生成的,jsonb_build_object() 函数

标签: java json spring-boot jackson


【解决方案1】:

一种方法是创建一个Converter

public final class NoUTCInstant implements Converter<LocalDateTime, Instant> {
    @Override
    public Instant convert(LocalDateTime value) {
        return value.toInstant(ZoneOffset.UTC);
    }
    @Override
    public JavaType getInputType(TypeFactory typeFactory) {
        return typeFactory.constructType(LocalDateTime.class);
    }
    @Override
    public JavaType getOutputType(TypeFactory typeFactory) {
        return typeFactory.constructType(Instant.class);
    }
}

然后注释该字段。

@JsonDeserialize(converter = NoUTCInstant.class)
private Instant startedAt;

【讨论】:

    【解决方案2】:

    您尝试解析的字符串 2020-02-22T16:37:23 不以 Z 结尾。 Instant 期望这一点,因为它代表 UTC。它根本无法解析。将字符串与 Z 连接以解决问题。

            String customInstant = "2020-02-22T16:37:23";
    
            System.out.println("Instant of: " + Instant.parse(customInstant.concat("Z")));
    

    【讨论】:

    • JSON 由 Postgres 函数 jsonb_build_object() 生成。所以我将 SQL 查询更改为jsonb_build_object( 'recoveryId', r.recovery_id, 'startedAt', replace(concat(r.started_at, 'Z'), ' ', 'T'),,它有所帮助。谢谢!
    猜你喜欢
    • 2020-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-04
    • 2016-11-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多