问题描述
@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));
}
}
这就是我如何配置我的 objectMapper:
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addDeserializer(LocalDateTime.class,new LocalDateTimeDeserializer());
this.objectMapper.registerModule(javaTimeModule);
this.objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
this.objectMapper.registerModule(new Jdk8Module());
this.objectMapper.findAndRegisterModules();
应用程序在以下 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
我想,杰克逊将“dateTimeMessageSend”识别为一个对象,但无法将其解析为字符串。
- 修改源 json,例如将 LocalDateFormat 更改为 String。 (什么是不受欢迎的)
- 进一步自定义 objectMapper 或/和 LocalDateTimeDeserializer
解决方法
似乎对您实际收到的内容有些误解
在 deserialize
方法中,当 Jackson 调用您的 LocalDateTimeSerializer
时。
你不只是得到一个像
{ "month": "APRIL","dayOfYear": 109,... }
。
因此你不能简单地调用
jp.readValueAs(String.class);
这里有一个 MismatchedInputExcpetion
,因为解析器
遇到 {
而不是字符串 "something"
。
实际上你会得到一个令牌流(以{
开头)
您应该使用它直到结束 }
令牌,
从中提取相关部分,
并从这些部分构建一个 LocalDateTime
对象。
参见例如Baeldung - Getting started with deserialization in Jackson,
特别是那里给出的自定义解串器示例。
按照本教程,您可以像这样实现 deserialize
方法:
@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
。例如:它包含 "month": "APRIL"
and
"monthValue": 4
。因此,您无需提取所有
来自树的值,但只有其中一些。