如何使用Google GSON将JSON数组反序列化为泛型类型的集合? [英] How can I use Google GSON to deserialize a JSON array into a a Collection of a generic type?

查看:211
本文介绍了如何使用Google GSON将JSON数组反序列化为泛型类型的集合?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一些将用于从网站检索资源的代码。它看起来像这样:

  public Collection< Project> getProjects(){
String json = getJsonData(methods.get(Project.class)); //获取一个json列表,即[1,2,3,4]
Gson gson = new Gson();
Type collectionType = new TypeToken< Collection< Project>>(){} .getType();
返回gson.fromJson(json,collectionType);
}

所以很自然地我试着用Java泛型来抽象它。

  / * 
*反序列化一个json列表并返回给定类型的集合。
*
*示例用法:getData(AccountQuota.class) - >收集和LT; AccountQuota>
* /
@SuppressWarnings(unchecked)
public< T>收集和LT; T> getData(Class< T> cls){
String json = getJsonData(methods.get(cls)); //获取一个json列表,即[1,2,3,4]
Gson gson = new Gson();
Type collectionType = new TypeToken< Collection< T>>(){}。getType();
return(Collection< T>)gson.fromJson(json,collectionType);
}

代码的通用版本不太适合。

  public void testGetItemFromGetData()throws UserLoginError,ServerLoginError {
Map< String,String> userData = GobblerAuthenticator.authenticate(foo@example.com,mypassword);
String client_key = userData.get(client_key);
GobblerClient gobblerClient = new GobblerClient(client_key);
ArrayList< Project> machines = new ArrayList< Project>();
machines.addAll(gobblerClient.getData(Project.class));
assertTrue(machines.get(0).getClass()== Project.class);
Log.i(Machine,gobblerClient.getData(Project.class).toString());
}


java.lang.ClassCastException:无法在com.gobblertest.GobblerClientTest上将java.util.LinkedHashMap转换为com.gobbler.synchronization.Machine
。 testGetItemFromGetData(GobblerClientTest.java:53)
at java.lang.reflect.Method.invokeNative(Native Method)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:169)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:154)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:545)
at android.app.Instrumentation $ InstrumentationThread.run(Instrumentation。 java:1551)

有问题的类:

  import java.util.Map; 


公共类项目{
private int total_bytes_stored;
私人字符串名称;
私人字符串user_data_guid;
private int seqnum;
私人字符串guid;
私人地图current_checkpoint;
私人地图< String,String> upload_folder;
// TODO:schema_version
private boolean deleted;
// TODO:download_folders

public Project(){} //没有用于GSON的参数构造函数
}

我并不十分熟悉Java泛型或GSON内部的所有细节,而且我的搜索没有特别的信息。在这里有很多问题,但大多数都提到了像我原来那样的实现方法。而 GSON文档似乎并不以涵盖这种特殊情况。那么,如何使用Google GSON将JSON数组反序列化为泛型类型的集合?

不能。通用类型已被编译器清除,Gson无法知道您拥有哪些类型或其字段。


I'm writing some code that is going to be used to retrieve resources from a website. It all sort of looks like this:

public Collection<Project> getProjects() {
        String json = getJsonData(methods.get(Project.class)); //Gets a json list, ie [1, 2, 3, 4]
        Gson gson = new Gson();
        Type collectionType = new TypeToken<Collection<Project>>() {}.getType();
        return gson.fromJson(json, collectionType);
    }

So naturally I tried abstracting it using Java generics.

/*
     * Deserialize a json list and return a collection of the given type.
     * 
     * Example usage: getData(AccountQuota.class) -> Collection<AccountQuota>
     */
    @SuppressWarnings("unchecked")
    public <T> Collection<T> getData(Class<T> cls) {
        String json = getJsonData(methods.get(cls)); //Gets a json list, ie [1, 2, 3, 4]
        Gson gson = new Gson();
        Type collectionType = new TypeToken<Collection<T>>(){}.getType();
        return (Collection<T>) gson.fromJson(json, collectionType);
}

The generic version of the code doesn't quite work though.

public void testGetItemFromGetData() throws UserLoginError, ServerLoginError {
            Map<String,String> userData = GobblerAuthenticator.authenticate("foo@example.com", "mypassword");
            String client_key = userData.get("client_key");
            GobblerClient gobblerClient = new GobblerClient(client_key);
            ArrayList<Project> machines = new ArrayList<Project>();
            machines.addAll(gobblerClient.getData(Project.class));
            assertTrue(machines.get(0).getClass() == Project.class);
            Log.i("Machine", gobblerClient.getData(Project.class).toString());
        }


java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.gobbler.synchronization.Machine
at com.gobblertest.GobblerClientTest.testGetItemFromGetData(GobblerClientTest.java:53)
at java.lang.reflect.Method.invokeNative(Native Method)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:169)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:154)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:545)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1551)

The class in question:

import java.util.Map;


public class Project {
    private int total_bytes_stored;
    private String name;
    private String user_data_guid;
    private int seqnum;
    private String guid;
    private Map current_checkpoint;
    private Map<String, String> upload_folder;
    // TODO: schema_version
    private boolean deleted;
    // TODO: download_folders

    public Project() {} // No args constructor used for GSON
}

I'm not quite familiar with all the details of Java generics or GSON internals and my search has not been particularly informative. There a bunch of questions here on SO, but most refer to implementing methods like the original one I had. And the GSON docs don't seem to cover this particular case. So again, how can I use Google GSON to deserialize a JSON array into a a Collection of a generic type?

解决方案

Sadly, you can't. The generic type has been erased by the compiler, and there's no way for Gson to know what types you have or what their fields are.

这篇关于如何使用Google GSON将JSON数组反序列化为泛型类型的集合?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆