使用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
相关产品推荐
相关产品推荐

