使用Gson反序列化接口类型数据时无法获取返回值,求解决方案
解决Gson反序列化接口类型数据无法获取返回值的问题
我来帮你搞定这个Gson反序列化接口类型的问题!首先咱们得先弄清楚问题出在哪:
你注册了SubDataImplInstanceCreator来创建SubData接口的实例,这一步没问题,但Gson在反序列化时,虽然能成功创建SubDataImpl的对象,却不知道该把JSON里的字段(比如hello)赋值给这个实例的属性——因为SubData接口本身并没有hello这个属性,Gson默认不会处理接口实现类的字段。再加上你序列化的时候,JSON里并没有记录这个实例是SubDataImpl类型,Gson就更不知道该怎么映射字段了。
下面给你两种可行的解决方案:
方案1:使用RuntimeTypeAdapterFactory(推荐,支持多态场景)
这个工具类会在序列化时给JSON添加类型标识,反序列化时根据标识找到对应的实现类,完美解决多态类型的序列化/反序列化问题。
修改你的代码如下:
// 1. 创建RuntimeTypeAdapterFactory,指定父接口和实现类 RuntimeTypeAdapterFactory<SubData> subDataAdapterFactory = RuntimeTypeAdapterFactory.of(SubData.class) .registerSubtype(SubDataImpl.class); // 2. 注册到GsonBuilder GsonBuilder builder = new GsonBuilder(); builder.registerTypeAdapterFactory(subDataAdapterFactory); Gson gson = builder.create(); // 后续的序列化反序列化逻辑不变 Dataclass data = new Dataclass(); data.key1 = "abc"; SubDataImpl subData = new SubDataImpl(); subData.hello = "ttt"; data.sub = subData; String jsonValue = gson.toJson(data); System.out.println(jsonValue); // 此时JSON会多一个type字段,比如"type":"SubDataImpl" Dataclass data2 = gson.fromJson(jsonValue, Dataclass.class); // 现在data2.sub的hello属性会正确赋值为"ttt"
方案2:自定义TypeAdapter(无需额外依赖,适合简单场景)
如果你不想引入额外依赖,也可以自己写一个TypeAdapter,手动处理SubData类型的序列化和反序列化:
// 自定义SubData的TypeAdapter class SubDataAdapter extends TypeAdapter<SubData> { @Override public void write(JsonWriter out, SubData value) throws IOException { // 序列化时,把SubData实例当作SubDataImpl处理 if (value instanceof SubDataImpl) { new Gson().getAdapter(SubDataImpl.class).write(out, (SubDataImpl) value); } else { out.nullValue(); } } @Override public SubData read(JsonReader in) throws IOException { // 反序列化时,直接解析JSON并创建SubDataImpl实例 JsonObject jsonObj = JsonParser.parseReader(in).getAsJsonObject(); SubDataImpl subData = new SubDataImpl(); if (jsonObj.has("hello")) { subData.hello = jsonObj.get("hello").getAsString(); } return subData; } }
然后注册这个TypeAdapter到GsonBuilder:
GsonBuilder builder = new GsonBuilder(); builder.registerTypeAdapter(SubData.class, new SubDataAdapter()); Gson gson = builder.create(); // 后续逻辑不变,反序列化后data2.sub的hello属性会正确赋值
注意:使用上面两种方案后,你之前注册的SubDataImplInstanceCreator就不需要了——因为TypeAdapter或者RuntimeTypeAdapterFactory已经负责创建实例和字段映射了。
内容的提问来源于stack exchange,提问作者Elye
相关产品推荐
相关产品推荐

