使用泛型类读取Gson中的匿名类数组

时间:2017-05-13 05:17:31

标签: java android generics arraylist gson

我使用Gson序列化和反序列化json。

pojo class:

class myData{
    public String id;
    public String name;
 }

并使用此代码我将json转换为pojo类。

public static Object getData(Class clazz)  {
    String json = "{'name':'john','id':'123'}";
        Gson gson = new Gson();
        return gson.fromJson(json , clazz);
}



//usage:
myData mdata= (myData) getData(myData.class);

每件事都没问题,在json的读数组中我有这个方法:

ArrayList<myData> getDatas() {
        ArrayList<myData> mdatas = new ArrayList<>();
        String json ="[{'name':'john','code':'123'},{'name':'nick','code':'456'}]";
        Type listType = new TypeToken<ArrayList<myData>>() {
        }.getType();
        if (new Gson().fromJson(json, listType) != null) {
            return new Gson().fromJson(json, listType);
        } else {
            return mdatas;
        }
}

该代码很好。但是我希望在getDatas中传递任何类,并在json中找到该类,然后在结果中返回该类的列表。

类似的东西:

 ArrayList<?> getDatas(Class clazz) {
    ArrayList<clazz> mdatas = new ArrayList<>();  //this line is the problem
    String json = "[{'name':'john','code':'123'},{'name':'nick','code':'456'}]";
    //and this line
    Type listType = new TypeToken<ArrayList<clazz>>() {
    }.getType();
    if (new Gson().fromJson(json, listType) != null) {
        return new Gson().fromJson(json, listType);
    } else {
        return mdatas;
    }
}

问题是不能在arraylist中使用匿名类。

 ArrayList<clazz> mdatas = new ArrayList<>(); 
 Type listType = new TypeToken<ArrayList<clazz>>() {

是否可以使用arraylist和匿名类?

2 个答案:

答案 0 :(得分:1)

您的问题是“Class”类型的实例与泛型类型不同。

请考虑以下事项:

<T> ArrayList<T> getDatas(Class<T> clazz) {
    ArrayList<T> mdatas = new ArrayList<>();  //this line is the problem
    String json = "[{'name':'john','code':'123'},{'name':'nick','code':'456'}]";
    //and this line
    Type listType = new TypeToken<ArrayList<T>>() {
    }.getType();
    if (new Gson().fromJson(json, listType) != null) {
        return new Gson().fromJson(json, listType);
    } else {
        return mdatas;
    }
}

这将赋予函数绑定的泛型类型,并且可以在这种情况下使用clazz参数的地方使用,这样就不必将其传入。

答案 1 :(得分:1)

如果您传递任何类型的令牌(用于编译时类型安全)或任何Type实例,这很容易。

使用类型标记

以下来源可以是StringReaderJsonReader中的任何一个(请参阅fromJson重载)。

static <E> List<E> getList(final ... source, final TypeToken<? extends List<E>> listTypeToken) {
    return gson.fromJson(source, listTypeToken.getType());
}

使用示例:

final List<MyData> list = getList(jsonReader, new TypeToken<List<MyData>>() {
});

顺便说一下,TypeTokenGson个实例是线程安全的,可以缓存到static final个字段。

使用没有类型令牌的任何类型

static <E> List<E> getList(final ... source, final Type type) {
    return gson.fromJson(source, getParameterized(List.class, type).getType());
}

此案例使用较新的Gson版本创建ParameterizedType实例。请注意,您可以动态创建类型(不要与创建类混淆):指定参数化类型List并使用给定的type对其进行参数化。

使用示例:

final List<MyData> list = getList(jsonReader, MyData.class);

如果你不能使用最新的Gson版本,你必须自己创建一个ParameterizedType实例(匿名类接口很容易理解):

static <E> List<E> getListForOlderGson(final ... source, final Type type) {
    return gson.fromJson(source, new ParameterizedType() {
        @Override
        public Type getRawType() {
            return List.class;
        }

        @Override
        public Type[] getActualTypeArguments() {
            return new Type[]{ type };
        }

        @Override
        public Type getOwnerType() {
            return null;
        }
    });
}