【问题标题】:Gson's RuntimeTypeAdapterFactory isn't serializing the typeGson 的 RuntimeTypeAdapterFactory 没有序列化类型
【发布时间】:2019-03-05 18:50:38
【问题描述】:

多年来我一直愉快地使用 gson,需要对一些多态类型进行序列化和反序列化,然后遇到了这个 gson extra,这似乎正是我所需要的:

https://github.com/google/gson/blob/master/extras/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java

但是无论我尝试什么,它都不会序列化类型字段,所以当它尝试反序列化时,自然会出现这个错误:

无法反序列化类 <...> 因为它没有定义名为 type 的字段

即使使用文件中的演示代码也不适合我:

class Shape {
  int x;
  int y;
}

class Diamond extends Shape {
  int width;
  int height;
}

...

Gson g = (new GsonBuilder()).registerTypeAdapterFactory(
    RuntimeTypeAdapterFactory
        .of(Shape.class)
        .registerSubtype(Diamond.class)
).create();

Diamond d = new Diamond();
d.x = 10;
d.y = 20;
d.width = 25;
d.height = 35;

String json = g.toJson(d);

产生:

{"width":25,"height":35,"x":10,"y":20}

注意我已经尝试为 of()register() 指定自定义字符串,将类型添加到 toJson() 调用,甚至将对象嵌入到外部集合中,但没有区别。

实际上,标准 Gson 对象与使用构建器和类型工厂创建的对象之间的输出没有区别。

我注意到如果我在 RuntimeTypeAdapterFactory 读取和写入方法中调试代码并设置断点,它会命中 read()(然后到达上面的失败),但它永远不会命中写方法。完全跳过它。

这里发生了什么?我使用的代码都是最新的,直接来自上面的链接(截至今天)。

【问题讨论】:

    标签: java json gson


    【解决方案1】:

    感谢公共存储库贡献者的帮助,问题在于包含基本类型所需的序列化步骤。所以不要简单地:

    g.toJson(d);
    

    必须是:

    g.toJson(d, Shape.class);
    

    我试过g.toJson(d, Diamond.class),但这对输出没有影响。希望这可以帮助其他人!

    【讨论】:

      【解决方案2】:

      rjcarr 的解决方案(在调用toJson 时包含类对象)并不实用,因为您通常将多态对象作为其他对象的成员或作为列表中的元素。

      实际上RuntimeTypeAdapterFactory 中存在一个错误。在 this github post 用户 ultraon 提出了一个对我有用的解决方案:

      替换

      if (type.getRawType() != baseType)
      

      if (null == type || !baseType.isAssignableFrom(type.getRawType()))
      

      在第 185 行,RuntimeTypeAdapterFactory 类的方法 create

      现在 type 属性包含在 JSON 中。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-12-09
        • 1970-01-01
        • 2015-05-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多