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

使用Gson序列化含LocalDateTime的类时出现Java反射访问错误

问题原因

这不是Gson的问题,是Java 9+模块系统的权限限制导致的。Gson默认通过反射访问LocalDateTime的私有字段(比如date),但java.base模块未将java.time包开放给你的代码所在的未命名模块,因此抛出InaccessibleObjectException。

解决方案

以下三种方案按推荐程度排序:

1. 使用Gson官方Java 8时间扩展模块

这是最规范的方案,无需绕开模块权限限制:

  • 添加Gson Java 8扩展依赖(以Maven为例,版本需与你的Gson主版本一致):
    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson-java8</artifactId>
        <version>2.10.1</version>
    </dependency>
    
  • 创建Gson实例时注册JavaTimeModule,它会自动处理LocalDateTime等Java 8时间类型:
    Gson gson = new GsonBuilder()
        .registerModule(new JavaTimeModule())
        .create();
    
    序列化后的LocalDateTime会以ISO-8601格式字符串输出,同时避免了反射访问私有字段的问题。

2. 添加JVM启动参数开放模块权限

如果不想引入额外依赖,可通过JVM参数放宽模块访问限制:

  • 精准开放java.time包给未命名模块(推荐,安全性更高):
    --add-opens java.base/java.time=ALL-UNNAMED
    
  • 全局放宽非法访问限制(不推荐,安全性低):
    -Djdk.module.illegalAccess=permit
    

3. 自定义TypeAdapter处理LocalDateTime

自行实现序列化/反序列化逻辑,完全避免反射:

public class LocalDateTimeAdapter extends TypeAdapter<LocalDateTime> {
    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ISO_LOCAL_DATE_TIME;

    @Override
    public void write(JsonWriter out, LocalDateTime value) throws IOException {
        if (value == null) {
            out.nullValue();
            return;
        }
        out.value(FORMATTER.format(value));
    }

    @Override
    public LocalDateTime read(JsonReader in) throws IOException {
        if (in.peek() == JsonToken.NULL) {
            in.nextNull();
            return null;
        }
        return LocalDateTime.parse(in.nextString(), FORMATTER);
    }
}

注册到GsonBuilder:

Gson gson = new GsonBuilder()
    .registerTypeAdapter(LocalDateTime.class, new LocalDateTimeAdapter())
    .create();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 22:52:51