You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过自定义反序列化器使用Jackson解析GSON生成的含LocalDate字段的JSON

解决Jackson反序列化自定义日期结构的问题

这个问题我碰到过好多次——Jackson默认没法直接识别这种嵌套了year/month/day的日期结构,所以咱们得写个自定义反序列化器来处理它。下面一步步来搞定:

1. 先定义你的实体类

首先得有个对应JSON结构的实体类,比如叫Article,这里我推荐用Java 8的LocalDate来存日期(比老的Date类好用太多):

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import java.math.BigDecimal;
import java.time.LocalDate;

public class Article {
    private int id;
    private int articleNumber;
    // 用注解指定咱们的自定义反序列化器
    @JsonDeserialize(using = CustomDateDeserializer.class)
    private LocalDate processDate;
    private BigDecimal price;

    // 一定要加无参构造器,Jackson需要它来实例化对象
    public Article() {}

    // 别忘了写getter和setter方法
    public int getId() { return id; }
    public void setId(int id) { this.id = id; }
    public int getArticleNumber() { return articleNumber; }
    public void setArticleNumber(int articleNumber) { this.articleNumber = articleNumber; }
    public LocalDate getProcessDate() { return processDate; }
    public void setProcessDate(LocalDate processDate) { this.processDate = processDate; }
    public BigDecimal getPrice() { return price; }
    public void setPrice(BigDecimal price) { this.price = price; }
}

2. 编写自定义反序列化器

接下来写核心的CustomDateDeserializer,继承Jackson的StdDeserializer,重写deserialize方法来解析嵌套的日期字段:

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import java.io.IOException;
import java.time.LocalDate;

public class CustomDateDeserializer extends JsonDeserializer<LocalDate> {

    @Override
    public LocalDate deserialize(JsonParser parser, DeserializationContext context) throws IOException {
        // 把当前节点转成JsonNode,方便提取里面的year/month/day
        JsonNode dateNode = parser.getCodec().readTree(parser);
        int year = dateNode.get("year").asInt();
        int month = dateNode.get("month").asInt();
        int day = dateNode.get("day").asInt();
        
        // 用拿到的数值构建LocalDate对象
        return LocalDate.of(year, month, day);
    }
}

3. 测试反序列化效果

最后写个测试代码,验证一下能不能正常解析你的JSON字符串:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import java.io.IOException;

public class TestDeserialization {
    public static void main(String[] args) throws IOException {
        String json = "{ \"id\": 10, \"articleNumber\": 5009, \"processDate\": { \"year\": 2021, \"month\": 1, \"day\": 1 }, \"price\": 1.22 }";
        
        ObjectMapper objectMapper = new ObjectMapper();
        // 注册JavaTimeModule,不然Jackson识别不了LocalDate类型
        objectMapper.registerModule(new JavaTimeModule());
        
        Article article = objectMapper.readValue(json, Article.class);
        
        // 打印结果看看是否正确
        System.out.println("ID: " + article.getId());
        System.out.println("Article Number: " + article.getArticleNumber());
        System.out.println("Process Date: " + article.getProcessDate());
        System.out.println("Price: " + article.getPrice());
    }
}

额外小提示

  • 如果你坚持要用老的java.util.Date,只需要把实体类里的LocalDate换成Date,然后在反序列化器里用new GregorianCalendar(year, month-1, day).getTime()(注意Calendar的月份是从0开始的,要减1)。
  • 除了用@JsonDeserialize注解单独指定,你也可以把反序列化器注册到ObjectMapper全局生效,这样所有同类型的日期字段都能自动解析:
    SimpleModule module = new SimpleModule();
    module.addDeserializer(LocalDate.class, new CustomDateDeserializer());
    objectMapper.registerModule(module);
    

这样就能完美解决你遇到的processDate字段反序列化失败的问题啦!

内容的提问来源于stack exchange,提问作者akr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 19:57:26