【问题标题】:Use Gson library with a generic class as a field of the class to serialize使用带有泛型类的 Gson 库作为类的字段进行序列化
【发布时间】:2016-10-25 08:31:31
【问题描述】:

在对 Google 和 Stack Overflow 进行了多次研究后,我还没有找到与我类似的案例。

我需要使用 Gson 库将 Java 对象转换为 Json。事实上,这个对象包含一个自定义泛型类型的字段,如下所示:

SendData.java:

public class SendData {
  private SendDataRequestObject<?> sendData;

  // Constructor + Getters and Setters
}

这里是 SendDataRequestObject 的类定义:

public class SendDataRequestObject<T> {
  private String actionType;
  private T parameters;
  private CustomClass customClass;

  //Constructor + Getters and Setters
}

最后是 MyRequest 的类定义,可以作为 T 参数注入到 SendDataRequestObject 中

public class MyRequest {
  private Map<Integer, String> myMap;
  private String myString1;
  private String myString2;

  //Constructor + Getters and Setters
}

实际上,我可以使用 Gson 库解析 SendDataRequestObject,如下所示:

SendDataRequestObject<MyRequest> requestObject = new SendDataRequestObject<MyRequest>();
//...
//Initializing and adding fields to requestObject
//...
Type token = new TypeToken<SendDataRequestObject<MyRequest>>(){}.getType();
System.out.println(new GsonBuilder().create().toJson(requestObject, token));

输出设置正确,每个字段,即使是通用字段,都包含在最终的 json 字符串中:

{"actionType":"verify","parameters":{"myMap":{"15789":"hreher-489hre-gdsf","13057":"rtyuiop-4g8ezg","16741":"gfd456-uiop789"},"myString1":"myStringValue1","myString2":"myStringValue2"},"customClas":{"attr1":"value1","attr2":"value2"}}

但我需要的是解析 SendData 类,而不是 SendDataRequestObject 类。当我尝试将此类转换为 json 字符串时,我得到了这个输出:

{"sendData":{"actionType":"verify","parameters":{},"customClass":{"attr1":"value1","attr2":"value2"}}}

所以,我们可以看到SendDataRequestObject的parameters字段没有转换成Json,可能是因为这是一个泛型类。

如果有人知道怎么做,我将不胜感激!

【问题讨论】:

    标签: java json generics gson


    【解决方案1】:

    由于 Java 的类型擦除,如果在编译时以某种方式不知道 T 的类型,您将无法执行此操作。

    一个选项是 JSON 可以包含一些指定类型的信息,例如

    {
      "sendDataType": "MyRequest",
      "sendData": {
         ...
       }
    }
    

    如果您随后将 SendData 设为通用,例如

    SendData<T> { 
      private SendDataRequestObject<T> sendData; 
    }
    

    然后您可以解析一次 JSON 以找出 sendDataType:

    SendData<?> genericSendData = new GsonBuilder().create().toJson(requestObject, new TypeToken<SendData<?>>(){});
    String sendDataType = genericSendData.sendDataType;
    

    并使用它来创建正确类型的TypeToken

    switch(sendDataType) {
      case "MyRequest":
        return new TypeToken<MyRequest>(){};
    }
    

    然后再次解析 JSON,指定泛型类型,因为您知道它:

    SendData<?> myRequestSendData = new GsonBuilder().create().toJson(requestObject, typeToken);
    

    这是可行的,因为我们的 switch 语句在编译时就知道可能的类型,并且可以为它们创建 TypeToken。

    【讨论】:

    • 感谢您的回答!我终于找到了另一个与您的非常相似的解决方案。正如您所说,在这种情况下,我们不得不在某处创建一个 switch 语句来检查 SendData 的类型,以便将其转换为 json 字符串。但是,您的解决方案似乎比我的更好、更清洁。谢谢你帮助我!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多