LocalDate序列化与反序列化问题:如何构造正确的JSON请求
解决LocalDate反序列化数组格式的问题
首先,你遇到的Cannot deserialize instance of java.time.LocalDate out of START_ARRAY token错误,核心原因有两个:
- Jackson的Java8日期模块默认只支持字符串格式的日期(比如
"1986-10-06"),不认识数组格式的日期输入; - 你当前的JSON格式本身就有问题:
[ 1986::10::06 ]是无效的JSON数组,数组元素不能是带双冒号的组合值,应该是三个独立的数字(比如[1986, 10, 06])。
下面给你两种可行的解决方案,按需选择:
方案一:修改JSON为标准字符串格式(最简单推荐)
直接把POST请求里的dob字段改成ISO-8601格式的字符串,这是Jackson Java8模块默认支持的格式,不需要额外配置:
{ "name" : "John", "dob" : "1986-10-06" }
这样发送请求后,Jackson会自动把字符串转成LocalDate对象,完美解决问题。
方案二:配置Jackson支持数组格式的LocalDate(如果必须用数组)
如果业务上必须用数组传递日期,可以通过以下两种方式实现:
方式1:给字段添加注解(局部配置)
在Student类的dob字段上添加@JsonFormat注解,指定日期的形状为数组,并匹配你的日期分隔符:
import com.fasterxml.jackson.annotation.JsonFormat; import java.time.LocalDate; public class Student { private String name; // 指定形状为数组,日期格式为yyyy::MM::dd @JsonFormat(shape = JsonFormat.Shape.ARRAY, pattern = "yyyy::MM::dd") private LocalDate dob; // getters and setters }
同时要修正你的JSON数组格式,改成三个数字元素:
{ "name" : "John", "dob" : [1986, 10, 06] }
这样Jackson就能正确识别数组中的年、月、日,转成LocalDate对象。
方式2:全局配置ObjectMapper(全局生效)
如果不想给每个日期字段都加注解,可以全局配置Jackson的ObjectMapper,让它同时支持数组和字符串格式的日期:
import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import java.io.IOException; import java.time.LocalDate; import java.time.format.DateTimeFormatter; public class JacksonGlobalConfig { public static ObjectMapper getConfiguredMapper() { ObjectMapper mapper = new ObjectMapper(); JavaTimeModule timeModule = new JavaTimeModule(); // 自定义LocalDate反序列化器,兼容数组和字符串格式 timeModule.addDeserializer(LocalDate.class, new StdDeserializer<LocalDate>(LocalDate.class) { @Override public LocalDate deserialize(com.fasterxml.jackson.core.JsonParser p, DeserializationContext ctxt) throws IOException { JsonNode node = p.getCodec().readTree(p); if (node.isArray()) { // 处理数组格式:取数组前三个元素作为年、月、日 int year = node.get(0).asInt(); int month = node.get(1).asInt(); int day = node.get(2).asInt(); return LocalDate.of(year, month, day); } else { // 处理字符串格式:兼容ISO-8601标准格式 return LocalDate.parse(node.asText(), DateTimeFormatter.ISO_LOCAL_DATE); } } }); mapper.registerModule(timeModule); return mapper; } }
配置完成后,不管是数组格式[1986,10,06]还是字符串格式"1986-10-06",都能被正确反序列化。
内容的提问来源于stack exchange,提问作者menteith
相关产品推荐
相关产品推荐

