【发布时间】:2019-12-02 13:46:12
【问题描述】:
背景
- 我有以下 JSON(来自 Kafka 的消息)
{
"markdownPercentage": 20,
"currency": "SEK",
"startDate": "2019-07-25"
}
- 我有以下(生成的 JSON 模式)POJO(我无法更改 POJO,因为它是公司的共享资源)
public class Markdown {
@JsonProperty("markdownPercentage")
@NotNull
private Integer markdownPercentage = 0;
@JsonProperty("currency")
@NotNull
private String currency = "";
@JsonFormat(
shape = Shape.STRING,
pattern = "yyyy-MM-dd"
)
@JsonProperty("startDate")
@NotNull
private ZonedDateTime startDate;
// Constructors, Getters, Setters etc.
}
- 我们的应用程序是一个 Spring Boot 应用程序,它使用 Spring Cloud Stream 从 Kafka 读取 JSON 消息 (1) 并使用 POJO (2),然后对其进行处理。
问题
当应用程序尝试将消息反序列化到对象时,它会抛出以下异常
com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.time.ZonedDateTime` from String "2019-07-25": Failed to deserialize java.time.ZonedDateTime: (java.time.DateTimeException) Unable to obtain ZonedDateTime from TemporalAccessor: {},ISO resolved to 2019-07-25 of type java.time.format.Parsed
at [Source: (String)"{"styleOption":"so2_GreyMelange_1563966403695_1361997740","markdowns":[{"markdownPercentage":20,"currency":"SEK","startDate":"2019-07-25"},{"markdownPercentage":20,"currency":"NOK","startDate":"2019-07-25"},{"markdownPercentage":20,"currency":"CHF","startDate":"2019-07-25"}]}"; line: 1, column: 126] (through reference chain: com.bestseller.generated.interfacecontracts.kafkamessages.pojos.markdownScheduled.MarkdownScheduled["markdowns"]->java.util.ArrayList[0]->com.bestseller.generated.interfacecontracts.kafkamessages.pojos.markdownScheduled.Markdown["startDate"])
at com.fasterxml.jackson.databind.exc.InvalidFormatException.from(InvalidFormatException.java:67)
at com.fasterxml.jackson.databind.DeserializationContext.weirdStringException(DeserializationContext.java:1549)
at com.fasterxml.jackson.databind.DeserializationContext.handleWeirdStringValue(DeserializationContext.java:911)
at com.fasterxml.jackson.datatype.jsr310.deser.JSR310DeserializerBase._handleDateTimeException(JSR310DeserializerBase.java:80)
at com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer.deserialize(InstantDeserializer.java:212)
at com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer.deserialize(InstantDeserializer.java:50)
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.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:286)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:245)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:27)
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:3004)
at com.bestseller.mps.functional.TestingConfiguration.test(TestingConfiguration.java:42)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.time.DateTimeException: Unable to obtain ZonedDateTime from TemporalAccessor: {},ISO resolved to 2019-07-25 of type java.time.format.Parsed
at java.base/java.time.ZonedDateTime.from(ZonedDateTime.java:566)
at com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer.deserialize(InstantDeserializer.java:207)
... 35 more
Caused by: java.time.DateTimeException: Unable to obtain ZoneId from TemporalAccessor: {},ISO resolved to 2019-07-25 of type java.time.format.Parsed
at java.base/java.time.ZoneId.from(ZoneId.java:463)
at java.base/java.time.ZonedDateTime.from(ZonedDateTime.java:554)
... 36 more
当前代码
我定义了以下 objectMapper
/**
* Date mapper.
*
* @return the {@link ObjectMapper}
*/
@Bean
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd"));
return mapper;
}
问题
我了解 POJO 中生成的 ZonedDateTime 需要一个源消息中不存在的“时间”元素。我只能控制 objectMapper。是否有任何可能的配置可以使这项工作?
注意
如果反序列化 POJO 中的时间元素“假定”为 startOfDay 即“00.00.00.000Z”,我很好
【问题讨论】:
-
你有直接反序列化到这种类型吗?本地日期与
ZonedDateTime完全不同。或者,您能否将Markdown中的属性更改为LocalDate?毕竟,这就是数据实际代表的内容。 -
我无法更改 POJO。也不是消息。生产者使用相同的 POJO 来生成消息。
-
我认为它适用于生产者,因为在杰克逊的 POJO 到 JSON 序列化过程中考虑了 @JsonFormat。
-
由于您从 JSON 收到的
startDate没有时间,我想您将时间设置为 00:00:00 不会有任何问题? -
正确。在 dezerialized POJO 中,如果“假定”时间元素为 00:00:00.000Z
标签: java json spring-boot jackson spring-cloud-stream