如何解决Gson反序列化含Instant字段的Java对象报错问题?
解决Gson反序列化Instant字段的类型不匹配异常
Gson默认不支持Java 8的Instant类型,当JSON中expireAt是字符串格式的时间戳,而实体类对应字段是Instant时,Gson无法自动完成转换,因此抛出Expected BEGIN_OBJECT but was STRING的异常。以下是几种可行的解决方法:
方案一:自定义Instant类型适配器
编写自定义的TypeAdapter处理字符串与Instant的相互转换,注册到Gson实例即可:
1. 实现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.Instant; import java.time.format.DateTimeFormatter; public class InstantTypeAdapter extends TypeAdapter<Instant> { private static final DateTimeFormatter ISO_INSTANT_FORMATTER = DateTimeFormatter.ISO_INSTANT; @Override public void write(JsonWriter out, Instant value) throws IOException { if (value == null) { out.nullValue(); return; } out.value(ISO_INSTANT_FORMATTER.format(value)); } @Override public Instant read(JsonReader in) throws IOException { if (in.peek() == JsonToken.NULL) { in.nextNull(); return null; } String timeStr = in.nextString(); return Instant.from(ISO_INSTANT_FORMATTER.parse(timeStr)); } }
2. 注册适配器并反序列化
Gson gson = new GsonBuilder() .registerTypeAdapter(Instant.class, new InstantTypeAdapter()) .create(); MyResponse myResponse = gson.fromJson(jsonString, MyResponse.class);
方案二:使用Gson官方Java 8时间扩展库
Gson提供了专门的扩展库支持Java 8时间类型,只需添加依赖并启用对应工厂:
1. 添加Maven依赖
<dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.10.1</version> <!-- 使用最新稳定版本 --> </dependency> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson-extras</artifactId> <version>2.10.1</version> </dependency>
2. 创建支持Java时间的Gson实例
import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.internal.bind.JavaTimeTypeAdapterFactory; Gson gson = new GsonBuilder() .registerTypeAdapterFactory(JavaTimeTypeAdapterFactory.create()) .create(); MyResponse myResponse = gson.fromJson(jsonString, MyResponse.class);
方案三:临时应急方案(不推荐长期使用)
如果不想修改Gson配置,可临时将实体类中的Instant字段改为String类型,后续在业务代码中手动转换:
1. 修改实体类
@Data @Builder public class Details { private String homeId; private String expireAt; // 将Instant改为String }
2. 手动转换为Instant
MyResponse myResponse = new Gson().fromJson(jsonString, MyResponse.class); for (Details detail : myResponse.getDetails()) { Instant expireInstant = Instant.parse(detail.getExpireAt()); // 业务逻辑中使用expireInstant }
内容的提问来源于stack exchange,提问作者newLearner
相关产品推荐
相关产品推荐

