用JacksonMapper反序列化Java 8 LocalDateTime

我已经在SO中阅读了一些关于答案的问题,这些问题与java.time.LocalDateTimeJSON属性之间的序列化和反序列化有关,但我似乎无法使其正常工作。

我已经设法将Spring Boot Application配置为以所需的格式(YYY-MM-dd

HH:mm)返回日期,但是在JSON中接受此格式的值时遇到了问题。

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

增加了对Maven的依赖jsr310

<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

如果我通过控制器访问此实体,则它将以正确的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> {

}

控制器:

@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完全没有作用。由于杰克逊正在执行反序列化,因此它对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;

}

}

以上是 用JacksonMapper反序列化Java 8 LocalDateTime 的全部内容, 来源链接: utcz.com/qa/418676.html

回到顶部