【问题标题】:Jackson converting LocalDatetime杰克逊转换 LocalDatetime
【发布时间】:2019-05-18 03:49:51
【问题描述】:

我有一个带有 @JsonFormat 的 LocalDateTime 字段

@JsonFormat(pattern = "yyyy-MM-dd'T'hh:mm:ss.SSS'Z'")
private LocalDateTime dateTime;

当 Jackson 尝试解析像 2018-11-28T15:24:00.000Z 这样的日期时,会引发异常

com.fasterxml.jackson.databind.JsonMappingException:无法构造 java.time.LocalDateTime 的实例:没有从字符串值反序列化的字符串参数构造函数/工厂方法('2018-11-28T15:24:00.000Z' )

在我的 pom.xml 我有:

  • 弹簧靴 1.5.7
  • jackson-datatype-jdk8
  • jackson-datatype-jsr310

我的 ObjectMapper Bean:

@Bean
public ObjectMapper postConstruct() {
    return this.builder
           .featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
            .defaultUseWrapper(false)
            .build();
}

我也试过了:

@JsonFormat(pattern = "yyyy-MM-dd'T'hh:mm:ss.SSS'Z'", timezone ="UTC")
private LocalDateTime dateTime;

【问题讨论】:

  • 您的数据类型错误。您的格式模式忽略了有价值的信息,最后的 Z 表示 UTC。删除'Z' 周围的引号。然后解析为InstantOffsetDateTime 来表示一个时刻。根据定义,LocalDateTime 不能 代表一个时刻,因为它故意缺少任何时区概念或与 UTC 的偏移量。
  • 我将LocalDateTime改为ZoneDateTime,去掉引号,但是抛出了JsonMappingException
  • Z 表示 UTC,而不是 full time zone。所以ZonedDateTime 不合适。 Instant 是您需要的课程:Instant.parse( "2018-11-28T15:24:00.000Z" )。抱歉,在杰克逊方面无法为您提供帮助。你搜索过堆栈溢出吗?已经多次询问并回答了杰克逊的日期时间访问。
  • 你试过用Date代替LocalDateTime@cvdr

标签: java spring-boot jackson


【解决方案1】:

我也遇到了同样的问题,并编写了自定义序列化器和反序列化器来解决问题。

下面是相同的代码sn-ps:

import static java.time.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME;
import java.io.IOException;
import java.time.LocalDateTime;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.node.TextNode;

public class JsonDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {

@Override
public LocalDateTime deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException,
        JsonProcessingException {
    ObjectCodec oc = jp.getCodec();
    TextNode node = (TextNode) oc.readTree(jp);
    String dateString = node.textValue();
    return LocalDateTime.parse(dateString, ISO_OFFSET_DATE_TIME);
    }
}


import static java.time.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME;
import java.io.IOException;
import java.time.LocalDateTime;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;

public class JsonDateTimeSerializer extends JsonSerializer<LocalDateTime> {
    @Override
    public void serialize(LocalDateTime date, JsonGenerator generator, SerializerProvider arg) throws IOException,
            JsonProcessingException {
        final String dateString = date.format(ISO_OFFSET_DATE_TIME);
        generator.writeString(dateString);
    }
}

**Using the above custom serializer and deserializer on the below request payload:**

    @JsonDeserialize(using = JsonDateTimeDeserializer.class)
    @JsonSerialize(using = JsonDateTimeSerializer.class)
    private LocalDateTime orderInitialized;

【讨论】:

    【解决方案2】:

    我在使用OffsetDateTime 时也遇到了这个问题。我只是添加了@JsonSerialize@JsonDeserialize(通过扩展JsonDeserializer&lt;&gt; 编写了自定义反序列化器)以及格式。问题解决了。

    【讨论】:

      【解决方案3】:

      我也遇到过类似的问题。此问题的原因是映射器无法从 String 对象创建 LocalDateTime 实例。下面将解决您的问题。

      @JsonSerialize(using = LocalDateTimeSerializer.class)
      @JsonDeserialize(using = LocalDateTimeDeserializer.class)
      @JsonFormat(pattern = "yyyy-MM-dd'T'hh:mm:ss.SSS'Z'")
      private LocalDateTime dateTime;
      

      如果您不想明确提及 Serializer/Deseralizer,则必须按照 JackSon 指南执行以下任一操作,以发布 DateTime Java 8 增强功能。

      ObjectMapper mapper = new ObjectMapper()
         .registerModule(new ParameterNamesModule())
         .registerModule(new Jdk8Module())
         .registerModule(new JavaTimeModule());
      

      ObjectMapper mapper = new ObjectMapper();
      mapper.findAndRegisterModules();
      

      在 SpringBoot 中,ObjectMapper 实例是 AutoWired 的,因此我不知道我们是否可以明确地执行任一解决方案。所以暂时,明确提及序列化器/反序列化器的肮脏解决方案是我最好的选择。

      JackSon Java8 LocalDateTime 增强自述页面如下

      https://github.com/FasterXML/jackson-modules-java8/blob/master/README.md

      【讨论】:

      • 格式应为“yyyy-MM-dd'T'HH:mm:ss.SSS'Z'”,大写“H”。否则,映射器将无法将字符串解析为 LocalDateTime,而是 LocalDate。因为“h”是 12 小时的演示文稿,需要“AM/PM”符号,根据答案:stackoverflow.com/a/52147072/4093741
      猜你喜欢
      • 1970-01-01
      • 2020-10-16
      • 2017-06-04
      • 2018-03-13
      • 2023-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-03
      相关资源
      最近更新 更多