提问者:小点点

使用ObjectMapper从JSON日期"dd.MM. yyyy HH:mm:ss"反序列化到OffsetDateTime


在测试中,我试图模拟DB的响应。Json:{描述:“测试描述”联系人电话:“123456789”创建日期:“18.04.2023 10:33:23”}

我的POJO有字段(OffsetDateTime createDate)。

这是我的测试

@ActiveProfiles("test")
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK, classes = ServiceRequestApp.class)
@AutoConfigureMockMvc
class CreateUpdateSrControllerTest {
    @Autowired
    private MockMvc mockMvc;

    @Autowired
    AbstractRestAdapter abstractRestAdapter;
    @MockBean
    SiebelDatabaseAdapter adapter;

    @Autowired
    GetSrService service;

    @Test
    void success_getSingleSR() throws Exception {
        DateTimeFormatter formatter = new DateTimeFormatterBuilder()
                .appendPattern("dd.MM.yyyy HH:mm:ss")
                .toFormatter();
        JavaTimeModule module = new JavaTimeModule();
        module.addDeserializer(OffsetDateTime.class, new CustomDeserializer(formatter));

        ObjectMapper objectMapper = JsonMapper.builder()
                .configure(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE, false)
                .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
                .addModule(module)
                .build();

        ServiceRequest response = objectMapper.readValue(new File("src/test/resources/GET_response.json"), ServiceRequest.class);
        Mockito.when(adapter.getSingleSrV2("1-824E20I0", "1-631532350728")).thenReturn(response);

        mockMvc.perform(get("/service-request")
                        .contentType(MediaType.APPLICATION_JSON)
                        .param("serviceRequest.id", "1-824E20I0")
                        .param("serviceRequest.number", "1-631532350728")
                        .header("x-channel-id", "test"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.description").value("testDescription"))
                .andExpect(jsonPath("$.contactPhone").value("123456789"));
    }

    private class CustomDeserializer extends JsonDeserializer<OffsetDateTime> {

        private DateTimeFormatter formatter;

        public CustomDeserializer(DateTimeFormatter formatter) {
            this.formatter = formatter;
        }

        @Override
        public OffsetDateTime deserialize(JsonParser parser, DeserializationContext context) throws IOException, JsonProcessingException {
            return OffsetDateTime.parse(parser.getText(), this.formatter);
        }
    }

}

正如你所看到的,我已经尝试了这个网站上的一些方法。但是它不适合我。

这是我的错误:


com.fasterxml.jackson.databind.JsonMappingException: Text '18.04.2023 10:33:44' could not be parsed: Unable to obtain OffsetDateTime from TemporalAccessor: {},ISO resolved to 2023-04-18T10:33:44 of type java.time.format.Parsed (through reference chain: ru.mts.cx.support.service.model.rest.ServiceRequest["createDate"])

    at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:392)
    at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:351)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.wrapAndThrow(BeanDeserializerBase.java:1821)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:316)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:177)
    at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:323)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4674)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3494)
    at ru.mts.cx.support.service.controller.CreateUpdateSrControllerTest.success_getSingleSR(CreateUpdateSrControllerTest.java:76)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
    at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
    at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
    at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
    at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
    at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
    at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
    at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: java.time.format.DateTimeParseException: Text '18.04.2023 10:33:44' could not be parsed: Unable to obtain OffsetDateTime from TemporalAccessor: {},ISO resolved to 2023-04-18T10:33:44 of type java.time.format.Parsed
    at java.base/java.time.format.DateTimeFormatter.createError(DateTimeFormatter.java:2023)
    at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1958)
    at java.base/java.time.OffsetDateTime.parse(OffsetDateTime.java:404)
    at ru.mts.cx.support.service.controller.CreateUpdateSrControllerTest$CustomDeserializer.deserialize(CreateUpdateSrControllerTest.java:100)
    at ru.mts.cx.support.service.controller.CreateUpdateSrControllerTest$CustomDeserializer.deserialize(CreateUpdateSrControllerTest.java:90)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:129)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:314)
    ... 74 more
Caused by: java.time.DateTimeException: Unable to obtain OffsetDateTime from TemporalAccessor: {},ISO resolved to 2023-04-18T10:33:44 of type java.time.format.Parsed
    at java.base/java.time.OffsetDateTime.from(OffsetDateTime.java:372)
    at java.base/java.time.format.Parsed.query(Parsed.java:241)
    at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1954)
    ... 79 more
Caused by: java.time.DateTimeException: Unable to obtain ZoneOffset from TemporalAccessor: {},ISO resolved to 2023-04-18T10:33:44 of type java.time.format.Parsed
    at java.base/java.time.ZoneOffset.from(ZoneOffset.java:350)
    at java.base/java.time.OffsetDateTime.from(OffsetDateTime.java:361)
    ... 81 more

尝试创建CustomDeserializer,添加DateTimeFor物质,在我的字段类型OffsetDateTime上方添加@JsonFormat(模式="dd.MM. yyyy HH:mm:ss")


共1个答案

匿名用户

字段createDate的类型是OffsetDateTime。要测试它,您的测试数据必须包含偏移量。即使它等于0。否则它无法解析。

解决方案

调整格式化程序以包含“Z”

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .appendPattern("dd.MM.yyyy HH:mm:ssZ")
            .toFormatter();

为测试数据添加偏移量

createDate: "18.04.2023 10:33:23+0000"