gpt4 book ai didi

java - 使用 JacksonMapper 反序列化 Java 8 LocalDateTime

转载 作者:IT老高 更新时间:2023-10-28 12:52:53 26 4
gpt4 key购买 nike

我已经在 SO 中阅读了几个关于 java.time.LocalDateTime 和 JSON 属性之间的序列化和反序列化的问题,但我似乎无法让它工作。

我已设法将我的 Spring Boot 应用程序配置为以我想要的格式返回日期 (YYY-MM-dd HH:mm),但我在接受这种 JSON 格式的值时遇到问题。

这些是我到目前为止所做的所有事情:

jsr310 添加了 maven 依赖:

<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>

在我的主类中指定 jsr310:

@EntityScan(basePackageClasses = { App.class, Jsr310JpaConverters.class })

application.properties 中禁用序列化作为时间戳:

spring.jackson.serialization.write_dates_as_timestamps=false

这是我的日期时间实体映射:

@Column(name = "start_date")
@DateTimeFormat(iso = DateTimeFormat.ISO.TIME)
@JsonFormat(pattern = "YYYY-MM-dd HH:mm")
private LocalDateTime startDate;

在我的数据库中,我将此日期存储为 TIMESTAMP,格式如下:2016-12-01T23:00:00+00:00

如果我通过 Controller 访问该实体,它会返回具有正确 startDate 格式的 JSON。当我尝试发布它并反序列化它时,使用 YYYY-MM-dd HH:mm 格式,我得到以下异常:

{
"timestamp": "2016-10-30T14:22:25.285+0000",
"status": 400,
"error": "Bad Request",
"exception": "org.springframework.http.converter.HttpMessageNotReadableException",
"message": "Could not read document: Can not deserialize value of type java.time.LocalDateTime from String \"2017-01-01 20:00\": Text '2017-01-01 20:00' could not be parsed: Unable to obtain LocalDateTime from TemporalAccessor: {MonthOfYear=1, WeekBasedYear[WeekFields[SUNDAY,1]]=2017, DayOfMonth=1},ISO resolved to 20:00 of type java.time.format.Parsed\n at [Source: java.io.PushbackInputStream@679a734d; line: 6, column: 16] (through reference chain: com.gigsterous.api.model.Event[\"startDate\"]); nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Can not deserialize value of type java.time.LocalDateTime from String \"2017-01-01 20:00\": Text '2017-01-01 20:00' could not be parsed: Unable to obtain LocalDateTime from TemporalAccessor: {MonthOfYear=1, WeekBasedYear[WeekFields[SUNDAY,1]]=2017, DayOfMonth=1},ISO resolved to 20:00 of type java.time.format.Parsed\n at [Source: java.io.PushbackInputStream@679a734d; line: 6, column: 16] (through reference chain: com.gigsterous.api.model.Event[\"startDate\"])",
"path": "/api/events"
}

我知道关于这个主题有很多答案,但是关注他们并尝试了几个小时并没有帮助我弄清楚我做错了什么,所以如果有人能向我指出我错过了什么,我会很高兴.感谢您对此的任何意见!

编辑:这些是该过程中涉及的所有类:

存储库:

@Repository
public interface EventRepository extends PagingAndSortingRepository<Event, Long> {
}

Controller :

@RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Event> createEvent(@RequestBody Event event) {
return new ResponseEntity<>(eventRepo.save(event), HttpStatus.CREATED);
}

我的 JSON 请求payalod:

{
"name": "Test",
"startDate": "2017-01-01 20:00"
}

事件:

@Entity
@Table(name = "events")
@Getter
@Setter
public class Event {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "event_id")
private long id;

@Column(name = "name")
private String name;

@Column(name = "start_date")
@DateTimeFormat(iso = DateTimeFormat.ISO.TIME)
@JsonFormat(pattern = "YYYY-MM-dd HH:mm")
private LocalDateTime startDate;
}

最佳答案

您传递的日期时间不是 ISO 本地日期时间格式。

改成

@Column(name = "start_date")
@DateTimeFormat(iso = DateTimeFormatter.ISO_LOCAL_DATE_TIME)
@JsonFormat(pattern = "YYYY-MM-dd HH:mm")
private LocalDateTime startDate;

并以“2011-12-03T10:15:30”格式传递日期字符串。

但如果你仍然想传递你的自定义格式,你只需要指定正确的格式化程序。

改成

@Column(name = "start_date")
@DateTimeFormat(iso = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"))
@JsonFormat(pattern = "YYYY-MM-dd HH:mm")
private LocalDateTime startDate;

我认为您的问题是 @DateTimeFormat 根本没有效果。由于 Jackson 正在进行反序列化,它对 spring 注释一无所知,我没有看到 spring 在反序列化上下文中扫描此注释。

或者,您可以尝试在注册 Java 时间模块时设置格式化程序。

LocalDateTimeDeserializer localDateTimeDeserializer = new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
module.addDeserializer(LocalDateTime.class, localDateTimeDeserializer);

这是带有解串器的测试用例,它工作正常。也许尝试完全摆脱那个 DateTimeFormat 注释。

@RunWith(JUnit4.class)
public class JacksonLocalDateTimeTest {

private ObjectMapper objectMapper;

@Before
public void init() {
JavaTimeModule module = new JavaTimeModule();
LocalDateTimeDeserializer localDateTimeDeserializer = new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
module.addDeserializer(LocalDateTime.class, localDateTimeDeserializer);
objectMapper = Jackson2ObjectMapperBuilder.json()
.modules(module)
.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.build();
}

@Test
public void test() throws IOException {
final String json = "{ \"date\": \"2016-11-08 12:00\" }";
final JsonType instance = objectMapper.readValue(json, JsonType.class);

assertEquals(LocalDateTime.parse("2016-11-08 12:00",DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm") ), instance.getDate());
}
}


class JsonType {
private LocalDateTime date;

public LocalDateTime getDate() {
return date;
}

public void setDate(LocalDateTime date) {
this.date = date;
}
}

关于java - 使用 JacksonMapper 反序列化 Java 8 LocalDateTime,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40327970/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com