【问题标题】:Deserialize LocalDateTime from String with Jackson使用杰克逊从字符串反序列化 LocalDateTime
【发布时间】:2018-09-03 09:10:34
【问题描述】:

我正在尝试使用 Jackson 将 String 反序列化为 LocalDateTime,但它不起作用。

我有一个带有 LocalDateTime 字段的数据类:

@Data
public class Registration {
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd hh:mm:ss")
    private LocalDateTime timestamp;
}

我添加了特殊的 Jackson 数据类型模块:

compile("com.fasterxml.jackson.datatype:jackson-datatype-jsr310")

序列化适用于:

new ObjectMapper().registerModule(new JavaTimeModule()).writeValueAsString(registration);

结果字符串:

{"timestamp":"2018-09-03 10:09:35"}

但反序列化不适用于:

new ObjectMapper().registerModule(new JavaTimeModule()).readValue(json.traverse(), Registration.class)

我得到的错误是:

Cannot deserialize value of type `java.time.LocalDateTime` from String "2018-09-03 10:09:35": 
    Failed to deserialize java.time.LocalDateTime: 
        (java.time.format.DateTimeParseException) Text '2018-09-03 10:09:35' could not be parsed: 
            Unable to obtain LocalDateTime from TemporalAccessor: 
                {MinuteOfHour=9, NanoOfSecond=0, SecondOfMinute=35, MicroOfSecond=0, MilliOfSecond=0, HourOfAmPm=10},
                ISO resolved to 2018-09-03 of type java.time.format.Parsed

我错过了什么?我对序列化有效但反序列化无效感到困惑。


MWE:(小型 gradle Java 项目)

Main.java:

import java.io.IOException;
import java.time.LocalDateTime;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.core.TreeNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;

public class Main {

    public static void main(String[] args) throws IOException {
        Registration registration = new Registration();
        registration.setTimestamp(LocalDateTime.now());

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

         String s = objectMapper.writeValueAsString(registration);
         TreeNode treeNode = objectMapper.readTree(s);

         //Fails here:
         Registration registration1 = objectMapper.readValue(treeNode.traverse(), Registration.class);

        System.out.println(registration1);
    }
}

class Registration {
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd hh:mm:ss")
    private LocalDateTime timestamp;

    public Registration() {
    }

    public LocalDateTime getTimestamp() {
        return this.timestamp;
    }

    public void setTimestamp(LocalDateTime localDateTime) {
        this.timestamp = localDateTime;
    }
}

build.gradle:

plugins {
    id 'java'
}

group 'dateMWE'
version '1.0-SNAPSHOT'

sourceCompatibility = 10

repositories {
    mavenCentral()
}

dependencies {
    compile("com.fasterxml.jackson.core:jackson-annotations:2.9.6")
    compile("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.6")
}

【问题讨论】:

    标签: java json jackson


    【解决方案1】:

    问题与JSON反序列化无关,与时间格式字符串有关:

    pattern = "yyyy-MM-dd hh:mm:ss"
    

    请注意,小时设置为 hh:这是一个 12 小时格式器,需要“AM”或“PM”值。

    如果模式改为

    pattern = "yyyy-MM-dd HH:mm:ss"
    

    问题应该解决了。

    【讨论】:

    • 确实如此。我玩过这个模式,但我找不到任何关于存在哪些模式/关键字的详细文档。您能否添加指向所有可能格式选项的文档或列表的链接?
    • @Spen:DataTimeFormatter 模式记录在标准Java API documentation
    • @Antot,感谢您的回答。它节省了我的时间。
    • 太棒了!!在看到您的答案之前,我挠了半天。你拯救了我的一天!
    • 感谢您拯救了我的一天。我参考stackoverflow.com/a/54819859/4093741这个答案,但代码不起作用。错误日志不是很直观。
    【解决方案2】:

    您的 ObjectMapper 不是由 spring 管理的,因为您正在使用 new 创建对象。在配置文件中将ObjectMapper 配置为 Bean。您需要使用您的LocalDateTimeDeserializer 注册DateTimeFormat。然后在 JavaTimeModule 中设置你的 Deserializer。

    @Bean
     Public ObjectMapper objectMapper() {
       JavaTimeModule module = new JavaTimeModule();
       LocalDateTimeDeserializer localDateTimeDeserializer =  new 
       LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
       module.addDeserializer(LocalDateTime.class, localDateTimeDeserializer);
       ObjectMapper objectMapperObj = Jackson2ObjectMapperBuilder.json()
                .modules(module)
                .featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
                .build();
    return objectMapperObj ;
    

    在你的 Spring 配置中设置上述配置。

    【讨论】:

    • 这对我有用,谢谢。
    猜你喜欢
    • 1970-01-01
    • 2017-06-04
    • 2018-10-19
    • 1970-01-01
    • 2023-03-04
    • 1970-01-01
    • 1970-01-01
    • 2015-04-07
    相关资源
    最近更新 更多