为什么 Gson.toJson 将通用字段序列化为空 JSON 对象?

2023-12-26

我有一个包含 T 类型字段的泛型类,Gson 将此字段序列化为空对象。我在下面添加了代码来演示该问题。读回 JSON 似乎没问题(只要您提供正确的类型标记)。

import java.lang.reflect.Type;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

public class GsonIssue {
    static class AbstractThing {
        private String fieldA = "valueA";

        public String getFieldA() {
            return fieldA;
        }

        public void setFieldA(String fieldA) {
            this.fieldA = fieldA;
        }

        @Override
        public String toString() {
            return "AbstractThing [fieldA=" + fieldA + "]";
        }
    }

    static class Thing extends AbstractThing {
        private String fieldB = "valueB";

        @Override
        public String toString() {
            return "Thing [fieldB=" + fieldB + ", fieldA=" + getFieldA() + "]";
        }
    }

    static class Wrapper<T extends AbstractThing> {
        private T abstractThing;
        private String standardField = "standard value";

        public Wrapper(T abstractThing) {
            this.abstractThing = abstractThing;
        }

        @Override
        public String toString() {
            return "Wrapper [abstractThing=" + abstractThing + ", standardField=" + standardField + "]";
        }
    }

    public static void main(String[] args) {
        Wrapper<Thing> wrapper = new Wrapper<Thing>(new Thing());

        Gson gson = new Gson();
        String json = gson.toJson(wrapper);
        System.out.println(json);
        // prints : {"abstractThing":{},"standardField":"standard value"}
        // so standardField is correctly serialized but not abstractThing.

        // but if we manually construct the expected json string, and parse it back, we get the expected object structure
        json = "{\"standardField\": \"some text\", " +
                "\"abstractThing\":{\"fieldB\" : \"arb value\", \"fieldA\" : \"another arb value\"}}";

        Type type = new TypeToken<Wrapper<Thing>>() {}.getType();
        Object fromJson = gson.fromJson(json, type);
        System.out.println(fromJson);
        // prints : Wrapper [abstractThing=Thing [fieldB=arb value, fieldA=another arb value], standardField=some text]
        // which is as expected
    }
}

来自他们的文档:

当您调用 toJson(obj) 时,Gson 会调用 obj.getClass() 来获取要序列化的字段的信息。同样,您通常可以在 fromJson(json, MyClass.class) 方法中传递 MyClass.class 对象。如果对象是非泛型类型,则此方法可以正常工作。但是,如果对象是泛型类型,则泛型类型信息会因为 Java 类型擦除而丢失

您可以通过为泛型类型指定正确的参数化类型来解决此问题。您可以使用 TypeToken 类来完成此操作。

他们给出了以下示例List<T>:

Type listType = new TypeToken<List<String>>() {}.getType();
gson.toJson(myStrings, listType);

所以对于你的代码,你需要......

Type myType = new TypeToken<Wrapper<Thing>>() {}.getType();
String json = gson.toJson(wrapper, myType);

https://sites.google.com/site/gson/gson-user-guide#TOC-Serializing-and-Deserializing-Gener https://sites.google.com/site/gson/gson-user-guide#TOC-Serializing-and-Deserializing-Gener

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 Gson.toJson 将通用字段序列化为空 JSON 对象? 的相关文章

  • 如何查看Pocketsphinx词典中是否存在该单词?

    我只是想看看字典文件中是否存在字符串 字典文件位于问题底部 我想检查语音识别器是否可以识别单词 例如 识别器将无法识别字符串ahdfojakdlfafiop 因为字典中没有定义 所以 我可以检查某个单词是否在 pocktsphinx 词典中
  • Google 地图查询返回的 JSON 包含像 \x26 这样的编码字符(如何解码?)

    在 Java 应用程序中 我获取 JSON 来自 Google 地图 其中包含以下字符 x26我想将其转换为其原始字符 据我所知 这是一个 UTF 8 表示法 但我不完全确定 在源 JSON 中 可能会出现各种编码字符 例如 x3c div
  • 如何从另一个xml文件动态更新xml文件?

    我想从另一个 xml 文件更新 xml 文件 我使用了一个 xml 文件 如下所示 one xml
  • JTree 节点不会被直观地选择

    不知何故 我无法为我的 JTree 节点启用 选择突出显示 我正在我的项目中使用自定义单元格渲染器 这很可能导致此问题 这是完整的渲染器类代码 protected class ProfessionTreeCellRenderer exten
  • 无法加载 jar 文件的主类

    我使用 Eclipse IDE 开发了一个应用程序 创建应用程序后 我以 jar 格式导出项目 当我尝试运行此 jar 文件时 出现错误 无法加载主类 请帮忙 当您将项目导出为 jar 时 请参阅此所以问题 https stackoverf
  • 如何对 IntStream 进行逆序排序

    我正在使用 txt 文件读取数字BufferedReader 我想颠倒该流中元素的顺序 以便在收集它们时 它们将从最高到最低排列 我不想在构建数组后进行排序 因为我不知道其中可能有多少元素 我只需要最高的 N 个元素 in new Buff
  • Java 泛型/类型调度问题

    考虑以下程序 import java util List import java util ArrayList public class TypeTest public static class TypeTestA extends Type
  • MI设备中即使应用程序被杀死,如何运行后台服务

    您好 我正在使用 alaram 管理器运行后台服务 它工作正常 但对于某些 mi 设备 后台服务无法工作 我使用了服务 但它无法工作 如何在 mi 中运行我的后台服务 MI UI有自己的安全选项 所以你需要的不仅仅是上面提到的粘性服务 你需
  • Android - 除了普通 SSL 证书之外还验证自签名证书

    我有一个通过 SSL 调用 Web 服务的 Android 应用程序 在生产中 我们将拥有由受信任的 CA 签名的普通 SSL 证书 但是 我们需要能够支持自签名证书 由我们自己的 CA 签名 我已经成功实施了接受自签名证书的建议解决方案
  • PropertySources 中各种源的优先级

    Spring引入了新的注释 PropertySources对于所有标记为的类 Configuration since 4 0 需要不同的 PropertySource作为论证 PropertySources PropertySource c
  • 想要开发像 Facebook 这样的网站 - 处理数百万个请求 - 高性能 [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我想用 Java 开发一个像 Fac
  • @EnableTransactionManagement 的范围是什么?

    我试图了解正确的放置位置 EnableTransactionManagement多个 JavaConfig 上下文的情况下的注释 考虑以下场景 我在 JPAConfig java 和 AppConfig java 中有 JPA 配置以及一组
  • 尝试在没有 GatewayIntent 的情况下访问消息内容

    我希望每当我写一条打招呼的消息时 机器人都会在控制台中响应一条消息 但它只是给我一个错误 JDA MainWS ReadThread WARN JDA Attempting to access message content without
  • 为什么 ConcurrentHashMap::putIfAbsent 比 ConcurrentHashMap::computeIfAbsent 更快?

    使用 ConcurrentHashMap 我发现computeIfAbsent 比putIfAbsent 慢两倍 这是简单的测试 import java util ArrayList import java util List import
  • 覆盖 MATLAB 默认静态 javaclasspath 的最佳方法

    MATLAB 配置为在搜索用户可修改的动态路径之前搜索其静态 java 类路径 不幸的是 静态路径包含相当多非常旧的公共库 因此如果您尝试使用新版本 您可能最终会加载错误的实现并出现错误 例如 静态路径包含 google collectio
  • 让JScrollPane控制多个组件

    对于我的应用程序 我正在设计一个脚本编辑器 目前我有一个JPanel其中包含另一个JPanel保存行号 位于左侧 以及JTextArea用于允许用户输入代码 位于右侧 目前 我已经实施了JScrollPane on the JTextAre
  • 如何为 Jackson 编写一个包罗万象的(反)序列化器

    当您提前知道类型时 编写自定义序列化器非常容易 例如 MyType一个人可以写一个MyTypeSerializer extends StdSerializer
  • 来自客户端的超时 Web 服务调用

    我正在使用 RestEasy 客户端调用网络服务 一项要求是 如果调用运行时间超过 5 秒 则中止 超时调用 我如何使用 RestEasy 客户端实现这一目标 我只看到服务器端超时 即如果在一定时间内未完成请求 Rest Easy 网络服务
  • Spock模拟inputStream导致无限循环

    我有一个代码 gridFSFile inputStream bytes 当我尝试这样测试时 given def inputStream Mock InputStream def gridFSDBFile Mock GridFSDBFile
  • 使用 eclipse IDE 配置 angularjs

    我想开始使用 AngularJs 和 Java Spring 进行开发 我使用 Eclipse 作为 IDE 我想配置我的 Eclipse 以使这些框架无缝工作 我知道我可能要求太多 但相信我 我已经做了很多研究 你们是我最后的选择 任何帮

随机推荐