LocalDateTime字段:不匹配PutException:无法反序列化“java.lang.String”的实例,因为它不属于START_对象标记

LocalDateTime字段:不匹配PutException:无法反序列化“java.lang.String”的实例,因为它不属于START_对象标记,java,jackson,deserialization,localdatetime,Java,Jackson,Deserialization,Localdatetime,我有一门主课: @NoArgsConstructor @AllArgsConstructor @Data @Builder public class ContentModel implements Serializable { @JsonProperty("serviceData") private ServiceData serviceData; } 和嵌套类: @NoArgsConstructor @AllArgsConstructor @Dat

我有一门主课:

@NoArgsConstructor
@AllArgsConstructor
@Data
@Builder
public class ContentModel implements Serializable {
    @JsonProperty("serviceData")
     private ServiceData serviceData;
}
和嵌套类:

 @NoArgsConstructor
 @AllArgsConstructor
 @Data
 @Builder
 public class ServiceData implements Serializable {
    @JsonProperty ("dateTimeMessageSend")
    private LocalDateTime dateTimeMessageSend;
 }
我正在尝试使用自定义反序列化程序反序列化此文件:

public class LocalDateTimeDeserializer extends StdDeserializer<LocalDateTime> {
   private static final long serialVersionUID = 1L;
   protected LocalDateTimeDeserializer() {
        super(LocalDateTime.class);
    }

   @Override
   public LocalDateTime deserialize(final JsonParser jp, final DeserializationContext ctxt)
         throws IOException {
       return LocalDateTime.parse(jp.readValueAs(String.class));
    }
 }
应用程序在以下json之外接收:

{
 "serviceData": {
    "dateTimeMessageSend": {
       "month": "APRIL",
       "dayOfYear": 109,
       "dayOfWeek": "MONDAY",
       "nano": 183251000,
       "year": 2021,
       "monthValue": 4,
       "dayOfMonth": 19,
       "hour": 14,
       "minute": 52,
       "second": 44,
       "chronology": {
          "calendarType": "iso8601",
          "id": "ISO"
         }
      },
    }
 }
在LocalDateTime反序列化时,我收到异常:

 MismatchedInputException: Cannot deserialize instance of `java.lang.String` out of START_OBJECT token
我想jackson会将“dateTimeMessageSend”识别为对象,而无法将其解析为字符串

解决这个问题的方法是什么

  • 修改源json,例如将LocalDateFormat更改为String。(什么是不可取的)
  • 进一步定制objectMapper或/和LocalDateTimeDeserializer

  • 对你实际收到的东西似乎有些误解 当Jackson调用您的
    LocalDateTimeSerializer
    时,在
    反序列化
    方法中

    你不只是得到一个像这样的长字符串
    {“月”:“四月”,“一年中的某一天”:109,…}
    。 因此,你不能只是简单地打电话

    jp.readValueAs(String.class);
    
    这里有一个
    不匹配的InputException
    ,因为解析器 遇到了一个
    {
    而不是字符串
    “something”

    实际上,您得到了一个令牌流(从
    {
    开始) 您应该在结账时使用的
    }
    令牌, 从中提取相关部分, 并从这些部分构建一个
    LocalDateTime
    对象

    比如说,, 特别是这里给出的自定义反序列化器示例。 遵循此教程,您可以实现如下的
    反序列化方法:

    @Override
    public LocalDateTime deserialize(final JsonParser jp, final DeserializationContext ctxt)
             throws IOException {
        JsonNode node = jp.getCodec().readTree(jp);
        int year = ((NumericNode) node.get("year")).asInt();
        int monthValue = ((NumericNode) node.get("monthValue")).asInt();
        int dayOfMonth = ((NumericNode) node.get("dayOfMonth")).asInt();
        int hour = ((NumericNode) node.get("hour")).asInt();
        int minute = ((NumericNode) node.get("minute")).asInt();
        int second = ((NumericNode) node.get("second")).asInt();
        return LocalDateTime.of(year, monthValue, dayOfMonth, hour, minute, second);
    }
    
    请注意,在接收到的JSON树中存在相当多的冗余
    LoclDateTime
    。例如:它包含
    “月”:“四月”
    “monthValue”:4
    。因此,您不需要提取所有
    树中的值,但只有部分值。

    如果接收到该JSON,则发送方未注册
    JavaTimeModule
    。强烈建议发送方进行修复。如果无法修复发送方,则需要自定义反序列化程序,该反序列化程序使用该方法从该JSON对象实例化
    LocalDateTime
    数据。安德烈亚斯,有些事情正在变得清晰。但你所说的“发送者得到修复”是什么意思?JSON的发送者不应该这样构建它。它应该是
    “dateTimeMessageSend”:“2021-04-19T14:52:44.183251”
    。如果可能的话,发送代码需要得到修复才能这样做。然后,在您的接收端解析将正常工作,而不需要自定义反序列化程序。是的,Andreas。我在sender object mapper JavaTimeModule中注册。问题解决了。您是对的。这是一个解决方案。但我找到了更简单的方法。我在s中注册ender对象映射器JavaTimeModule。问题是solved@Andrew是的,在发送方和接收方使用类似于“dateTimeMessageSend”的东西:“2021-04-19T14:52:44”
    要简单得多。
    @Override
    public LocalDateTime deserialize(final JsonParser jp, final DeserializationContext ctxt)
             throws IOException {
        JsonNode node = jp.getCodec().readTree(jp);
        int year = ((NumericNode) node.get("year")).asInt();
        int monthValue = ((NumericNode) node.get("monthValue")).asInt();
        int dayOfMonth = ((NumericNode) node.get("dayOfMonth")).asInt();
        int hour = ((NumericNode) node.get("hour")).asInt();
        int minute = ((NumericNode) node.get("minute")).asInt();
        int second = ((NumericNode) node.get("second")).asInt();
        return LocalDateTime.of(year, monthValue, dayOfMonth, hour, minute, second);
    }