【问题标题】:Jackson Data Binding for LocalDate[] using annotation使用注释的 LocalDate [] 的杰克逊数据绑定
【发布时间】:2019-04-27 10:14:01
【问题描述】:

我正在使用带有 Java 8 模块的 Jackson 将 JSON 文件转换为 Java 对象。但是在将 JSON 数组转换为 LocalDate[] 时,应用程序会抛出异常。

如何使用注解将下面的 JSON 数组转换为 LocalDate[]?

JSON

{
    "skip": [
        "01/01/2019",
        "26/01/2019"
    ]
}

代码

@JsonFormat(pattern = "dd/MM/yyyy")
@JsonSerialize(using = LocalDateSerializer.class)
@JsonDeserialize(using = LocalDateDeserializer.class)
private LocalDate[] skip;

例外

com.fasterxml.jackson.databind.exc.MismatchedInputException: Unexpected token (VALUE_STRING) within Array, expected VALUE_NUMBER_INT
 at [Source: (ByteArrayInputStream); line: 25, column: 3] (through reference chain: com.saalamsaifi.springwfrlroster.model.Team["skip"])
    at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
    at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1343)
    at com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer.deserialize(LocalDateDeserializer.java:110)
    at com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer.deserialize(LocalDateDeserializer.java:38)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:127)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:288)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4013)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3070)

【问题讨论】:

  • 去掉 JsonSerialize 和 JsonDeserialize 注释。
  • 为什么不完全省略@JsonSerialize@JsonDeserialize 注释,而是将JavaTimeModule 注册到您的ObjectMapper

标签: java spring-boot jackson jackson-databind jsr310


【解决方案1】:

乍一看:实际上是您的 json 数组中的 json 对象还是您展示的字符串?这应该是这样的: { “跳过”: [ "key1":"01/01/2019", “key2”:“2019 年 1 月 26 日” ] }

【讨论】:

    【解决方案2】:

    我怀疑查看您的代码和您的 json 模型,它正在尝试使用为一个对象定义的反序列化器将其转换为数组。简单来说,您试图将单个项目转换为它无法解析的数组。您可以尝试使用 LocalDate 列表。类似的东西:

    List<LocalDate> skip;
    

    您甚至可能需要根据日期序列化器创建自己的反序列化器。

    【讨论】:

      【解决方案3】:

      由于skip数组 类型,LocalDateSerializerLocalDateDeserializerJsonFormat 不能开箱即用 - 它们被实现为期望直接值令牌而不是数组。

      您可以实现自己的序列化器/反序列化器。我为反序列化您的示例而实施的一个简单的反序列化器如下:

      public class CustomLocalDateArrayDeserializer extends JsonDeserializer<LocalDate[]> {
      
        private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
      
        @Override
        public LocalDate[] deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
          ArrayList<LocalDate> list = new ArrayList<>();
          JsonToken currentToken = p.getCurrentToken();
          if (currentToken != JsonToken.START_ARRAY) {
            throw new JsonMappingException(p, "Not an array!");
          }
      
          currentToken = p.nextToken();
      
          while (currentToken != JsonToken.END_ARRAY) {
            if (currentToken != JsonToken.VALUE_STRING) {
              throw new JsonMappingException(p, "Not a string element!");
            }
      
            LocalDate localDate = LocalDate.parse(p.getValueAsString(), formatter);
            list.add(localDate);
      
            currentToken = p.nextToken();
          }
      
          return list.toArray(new LocalDate[0]);
        }
      }
      

      我将字段注释更改为@JsonDeserialize(using = CustomLocalDateArrayDeserializer.class)

      如果您认为值得付出努力,您可以对其进行迭代和改进,使其阅读并尊重@JsonFormat 注释等。

      【讨论】:

      • 没有必要做所有这些。只需删除注释就足够了。
      • 谢谢@Utku Özdemir,您的解决方案对我有用。但我想通过一些注释来做到这一点。
      猜你喜欢
      • 2019-11-11
      • 1970-01-01
      • 2015-05-18
      • 2017-07-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-05
      • 2015-05-02
      相关资源
      最近更新 更多