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

Jakarta EE Jsonb处理YearMonth反序列化报错求助(弃用Jackson)

解决Jakarta EE JSON-B反序列化java.time.YearMonth的错误

问题原因

Jakarta EE JSON-B(Jsonb)默认未内置java.time.YearMonth类型的序列化/反序列化支持,这是导致你遇到错误的核心原因。下面提供纯Jsonb生态的解决方案,无需依赖Jackson。


解决方案:自定义Jsonb类型适配器

通过实现JsonbAdapter接口,我们可以手动定义YearMonth与JSON字符串之间的转换逻辑,适配你需要的"年月"格式(如yyyy-MM)。

1. 编写YearMonth的Jsonb适配器

创建适配器类,处理YearMonth和字符串的双向转换:

import jakarta.json.bind.adapter.JsonbAdapter;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;

public class YearMonthJsonbAdapter implements JsonbAdapter<YearMonth, String> {
    // 定义JSON中使用的年月格式,可根据需求调整
    private static final DateTimeFormatter YEAR_MONTH_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM");

    @Override
    public String adaptToJson(YearMonth yearMonth) throws Exception {
        // 序列化:YearMonth转字符串
        return yearMonth != null ? yearMonth.format(YEAR_MONTH_FORMAT) : null;
    }

    @Override
    public YearMonth adaptFromJson(String jsonValue) throws Exception {
        // 反序列化:字符串转YearMonth
        return jsonValue != null && !jsonValue.isBlank() 
            ? YearMonth.parse(jsonValue, YEAR_MONTH_FORMAT) 
            : null;
    }
}

2. 应用适配器到代码中

有两种方式可以使用这个适配器,根据你的场景选择:

方式一:字段级单独配置

直接在实体类的publishedOn字段上标注@JsonbTypeAdapter,指定我们的适配器:

public class Book {
    public String isbn;
    public String title;
    
    @JsonbTypeAdapter(YearMonthJsonbAdapter.class)
    public YearMonth publishedOn;
}
方式二:全局配置(推荐多类使用场景)

如果你的项目中有多个类用到YearMonth类型,可以全局注册适配器,避免重复标注:

public static void main(String[] args) {
    // 创建Jsonb配置并注册适配器
    JsonbConfig config = new JsonbConfig()
            .withAdapters(new YearMonthJsonbAdapter());
    
    Jsonb jsonb = JsonbBuilder.create(config);
    
    // 序列化测试
    Book book = new Book();
    book.isbn = "123";
    book.title = "Advanced JPA and Hibernate";
    book.publishedOn = YearMonth.of(2022, 9);
    String serializedJson = jsonb.toJson(book);
    // 输出:{"isbn":"123","title":"Advanced JPA and Hibernate","publishedOn":"2022-09"}
    
    // 反序列化测试
    String testJson = "{\"isbn\":\"123\",\"title\":\"Advanced JPA and Hibernate\",\"publishedOn\":\"2022-09\"}";
    Book deserializedBook = jsonb.fromJson(testJson, Book.class);
    // deserializedBook.publishedOn 将正确解析为 YearMonth.of(2022,9)
}

与JPA转换器的兼容性说明

你当前使用的JPAYearMonthDateAttributeConverter负责将YearMonth映射到数据库DATE字段,而我们的Jsonb适配器仅处理JSON与Java对象的转换,二者职责分离,完全可以同时使用,不会产生冲突,完美满足你"仅存储年月信息"的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 15:16:03