java - 使用 Spring Boot 和 Jackson ObjectMapper 时 OffsetDateTime 属性 JSON 序列化的区别
问题描述
当我开始为基于 Spring Boot 的 REST API 编写测试时,我注意到OffsetDateTime
无论我使用 Spring MockMVC 执行请求还是使用 Jackson 来序列化 DTO 中的属性都不同ObjectMapper
。使用 Spring 时,我的@JSONFormat
注释使用正确,但使用时却ObjectMapper
没有。
@EqualsAndHashCode
@Builder
public class FooDTO{
public int id;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
public OffsetDateTime arrival;
public fooDTO(int id, OffsetDateTime arrival){
this.id = id;
this.arrival = arrival;
}
}
@RestController
public class FooController {
@Autowired
private FooRepository fooRepository;
@RequestMapping(value = "/foo/bar/{id}")
public fooDTO getFoo (@PathVariable int id) {
return fooRepository.loadDTO(id);
}
}
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = Application.class)
@WebMvcTest(FooController.class)
public class FooControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private FooRepository fooRepository;
@Test
public void fooTest() {
FooDTO fooDTO = FooDTO.builder().id(1).arrival(OffsetDateTime.now()).build();
String fooDTOJSON = new ObjectMapper().writeValueAsString(fooDTO);
when(fooRepository.loadDTO(1).thenReturn(fooDTO);
String reponse = mockMvc.perform(request(HttpMethod.GET, "/foo/bar/1").accept(APPLICATION_JSON).andReturn().getResponse().getContentAsString();
assertEquals(fooDTOJSON, response);
}
Spring MockMVC 响应如下所示:
{"id":1, "arrival": "2020-03-28 12:29:44"}
虽然 ObjectMapper 中的 fooDTOJSON 看起来像这样:
{"id":1, "arrival":{"offset":{"totalSeconds":3600,"id":"+01:00","rules":{"fixedOffset":true,"transitions":[],"transitionRules":[]}},"nano":697162400,"year":2020,"monthValue":3,"dayOfMonth":28,"hour":12,"minute":29,"second":44,"dayOfWeek":"SATURDAY","dayOfYear":88,"month":"MARCH"}}
理想情况下,我希望ObjectMapper
返回与 MockMVC 相同的结果并在 DTO 上使用我的注释。即使解决方案可能很明显,我也非常感谢有人对此提供帮助。我不太习惯在 Java 生态系统中工作,尤其是 Spring。
解决方案
导致预期结果的解决方案是添加jackson-modules-java8库(在我的情况下,由于 Spring(-Boot) 或我的应用程序的另一个依赖项,我认为它已经存在)并将相应的模块添加到 Jackson Mapper . 接收“正确” JSON 字符串的工作解决方案是:
String fooDTOJSON = new ObjectMapper().registerModule(new JavaTimeModule()).writeValueAsString(fooDTO);
推荐阅读
- swiper - 如何在 SwiperJS 容器外使用分页?
- database-project - 执行 DACPAC 文件时出错(使用 sqlpackage.exe)
- java - java反向三角形星形图案
- ios - 为所有 UIViewController 实例设置全局默认后退按钮显示模式
- git - git:将子模块分支重置为远程标签
- javascript - 如何期望记录器同时抛出错误并通过单元测试?
- python-3.x - 未显示 Voila 的 Ipywidgets:错误龙卷风未捕获异常 GET
- javascript - 如何在循环JS中仅触发一个按钮
- javascript - 条件与结果不符
- azure-data-factory-2 - 是否可以在 Azure 数据工厂中使用 MD5 哈希编码重命名文件名?