
2.6低版本Jackson序列化与反序列化:`Date` vs. `LocalDate` 以及版本差异
Jackson 序列化与反序列化:Date
vs. LocalDate
以及版本差异
遇到的问题
在低版本的Spring项目中,使用LocalDate
对象进行序列化和反序列化时,(作为dto和vo时),会出现序列化时抛出异常的情况。
Type definition error: [simple type, class java.time.LocalDate]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of java.time.LocalDate (no Creators, like default constructor, exist): no String-argument constructor/factory method to deserialize from String value ('2001-05-26')\n at [Source: (PushbackInputStream); line: 5, column: 22] (through reference chain: com.jhinno.appportal.api.center.bean.SimuTask[“sampling_time”])
使用Date
作为入参的类型时,要求格式为yyyy-MM-dd
,但是当你传入的参数为"2001-0588-2688"
,这样的字符串时,不会抛出异常,而是会保存成一个错误的日期。
而使用
LocalDate
对象时,要求格式为yyyy-MM-dd
,但是当你传入的参数为"2001-0588-2688"
,这样的字符串时,会抛出异常。
前提是你得jackson版本是2.6及以上的版本。
1. Date
vs. LocalDate
对象
Date
对象
- 特点:
Date
是Java中早期用于表示日期和时间的类,它包含日期和时间部分。Date
类本质上是一个时间戳,通常不包含时区信息。 - 兼容性:由于
Date
是Java 8之前的类,与许多序列化/反序列化库(如Jackson)兼容性较好。默认情况下,使用Date
对象进行序列化和反序列化通常不会出现问题。
LocalDate
对象
- 特点:
LocalDate
是Java 8引入的java.time
包中的类,专门用于表示没有时间部分的日期。LocalDate
不会保存时区或时间信息。 - 兼容性:尽管
LocalDate
更现代化和类型安全,但需要额外的配置才能与Jackson等序列化/反序列化库兼容。否则,Jackson可能会因为找不到适合的构造函数或工厂方法来处理字符串(如"2001-10-05"
)到LocalDate
的转换而报错。
2. Jackson 版本的区别
Jackson 早期版本(2.6之前)
日期处理的默认支持:Jackson的早期版本默认支持
java.util.Date
和java.sql.Date
。这些类是Java 8之前主要用于表示日期和时间的类,因此Jackson对它们的序列化和反序列化提供了内置支持。对于Date
类,Jackson会自动处理将其序列化为时间戳或ISO 8601日期格式的字符串。Java 8
java.time
API的处理:在这些早期版本中,Jackson不直接支持Java 8引入的java.time
类(如LocalDate
、LocalDateTime
等)。尝试使用这些类时,Jackson会因为无法找到适当的构造函数或工厂方法来处理这些类的序列化/反序列化而抛出异常。要支持java.time
类,开发者需要手动编写自定义的序列化器和反序列化器,或使用第三方库来处理。
Jackson 较新版本(2.6及之后)
对
java.time
API的增强支持:从Jackson 2.6版本开始,Jackson引入了对Java 8java.time
API的官方支持。通过引入com.fasterxml.jackson.datatype:jackson-datatype-jsr310
模块,Jackson可以直接处理LocalDate
、LocalDateTime
等类。通过注册JavaTimeModule
,Jackson能够自动序列化和反序列化这些类,而不再需要开发者手动编写序列化器和反序列化器。改进的日期和时间处理:较新版本的Jackson在日期和时间的处理上更加强大和灵活。例如,它能够更好地处理ISO 8601格式的日期字符串,提供对时区的支持,并且可以配置为禁用日期时间戳的序列化。另外,Jackson的新版本允许通过注解(如
@JsonFormat
)更灵活地控制日期格式和时区的配置。
3. @DateTimeFormat
vs. @JsonFormat
注解
**
@DateTimeFormat
**:这是Spring的注解,通常用于处理表单提交或URL中的日期字符串。它主要用于格式化请求参数。**
@JsonFormat
**:这是Jackson的注解,控制JSON序列化和反序列化的格式。对于日期类型,可以指定日期格式和时区,确保在序列化(Java对象转JSON)和反序列化(JSON转Java对象)时保持一致。
4. 注册 JavaTimeModule
为了让Jackson能够处理LocalDate
等java.time
包中的类,必须注册JavaTimeModule
模块,并且通常需要禁用将日期写为时间戳的功能。否则,Jackson会抛出InvalidDefinitionException
。
1 | import com.fasterxml.jackson.databind.ObjectMapper; |
总结
- Date对象与Jackson的兼容性好,通常不会遇到序列化和反序列化的问题。
- LocalDate对象更现代化,但需要通过注册
JavaTimeModule
和适当配置Jackson才能正确处理。 - 选择使用
Date
还是LocalDate
,取决于应用场景和项目的要求。对于新的项目,LocalDate
更符合现代编程规范,但使用时要确保正确配置。
如果你使用的是Java 8及以上版本,并且希望在项目中使用LocalDate
等现代化的日期类,建议使用Jackson的较新版本,并确保正确配置相关模块。