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

使用Gson反序列化含LocalDateTime字段的JSON时出现空指针异常

解决Gson反序列化LocalDateTime字段时的空指针异常问题

我之前也碰到过一模一样的问题!其实根源很明确:Gson默认不支持Java 8的LocalDateTime这类时间API的嵌套对象结构反序列化,直接解析的话会把JSON里的start、stop字段解析成null,等你后续访问这些字段的方法时,自然就触发NullPointerException了。

下面给你两种可行的解决方案,按需选择:

方案一:自定义TypeAdapter解析嵌套的LocalDateTime结构

因为你的JSON里start、stop是拆分成年份、月份等字段的对象,而不是标准的时间字符串,所以我们需要写一个适配这种结构的TypeAdapter:

首先创建适配器类:

import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.Month;

public class LocalDateTimeObjectAdapter extends TypeAdapter<LocalDateTime> {

    @Override
    public void write(JsonWriter out, LocalDateTime value) throws IOException {
        // 如果需要序列化LocalDateTime为这种结构,可以实现这个方法,这里先聚焦反序列化
        out.beginObject();
        out.name("year").value(value.getYear());
        out.name("month").value(value.getMonth().name());
        out.name("dayOfMonth").value(value.getDayOfMonth());
        out.name("hour").value(value.getHour());
        out.name("minute").value(value.getMinute());
        out.name("second").value(value.getSecond());
        out.name("nano").value(value.getNano());
        out.endObject();
    }

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

        int year = 0;
        Month month = null;
        int dayOfMonth = 0;
        int hour = 0;
        int minute = 0;
        int second = 0;
        int nano = 0;

        in.beginObject();
        while (in.hasNext()) {
            switch (in.nextName()) {
                case "year":
                    year = in.nextInt();
                    break;
                case "month":
                    month = Month.valueOf(in.nextString());
                    break;
                case "dayOfMonth":
                    dayOfMonth = in.nextInt();
                    break;
                case "hour":
                    hour = in.nextInt();
                    break;
                case "minute":
                    minute = in.nextInt();
                    break;
                case "second":
                    second = in.nextInt();
                    break;
                case "nano":
                    nano = in.nextInt();
                    break;
                // 忽略JSON中不需要的字段,比如dayOfWeek、chronology
                default:
                    in.skipValue();
                    break;
            }
        }
        in.endObject();

        return LocalDateTime.of(year, month, dayOfMonth, hour, minute, second, nano);
    }
}

然后在创建Gson实例时注册这个适配器,再进行反序列化:

// 注册适配器创建Gson实例
Gson gson = new GsonBuilder()
        .registerTypeAdapter(LocalDateTime.class, new LocalDateTimeObjectAdapter())
        .create();

// 假设你的顶层实体类是Metrics,直接反序列化
Metrics metrics = gson.fromJson(yourJsonString, Metrics.class);

方案二:确保实体类字段与JSON结构匹配

别忘了检查你的Java实体类,比如Measurement类的字段要和JSON严格对应,示例如下:

import java.time.LocalDateTime;
import java.util.List;

// Measurement类对应JSON中的单个测量项
public class Measurement {
    private String serviceName;
    private LocalDateTime start;
    private LocalDateTime stop;

    // 记得添加无参构造函数、getter和setter,Gson需要无参构造来实例化对象
    public Measurement() {}

    // getter和setter方法
    public String getServiceName() { return serviceName; }
    public void setServiceName(String serviceName) { this.serviceName = serviceName; }
    public LocalDateTime getStart() { return start; }
    public void setStart(LocalDateTime start) { this.start = start; }
    public LocalDateTime getStop() { return stop; }
    public void setStop(LocalDateTime stop) { this.stop = stop; }
}

// Metrics类对应顶层的metrics对象
public class Metrics {
    private List<Measurement> measurements;

    public Metrics() {}

    public List<Measurement> getMeasurements() { return measurements; }
    public void setMeasurements(List<Measurement> measurements) { this.measurements = measurements; }
}

额外提醒

如果你的JSON字段和实体类字段名不一致,可以用@SerializedName注解来映射,比如:

@SerializedName("service_name")
private String serviceName;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:54:50