简体   繁体   English

在 Gson 中使用泛型

[英]Using a generic type with Gson

I am trying to create a generic class for use with Google Gson .我正在尝试创建一个用于Google Gson的通用类。 I've created the class GsonJsonConverterImplementation<T> .我创建了类GsonJsonConverterImplementation<T> This class has the following method:这个类有以下方法:

public T deserialize(String jsonString) {
    GsonBuilder builder = new GsonBuilder();
    builder.setDateFormat("MM/dd/yy HH:mm:ss");

    Gson gson = builder.create();
    return gson.fromJson(jsonString, T); // T.class etc. what goes here
}

The goal is that this method should be able to work with whatever Type I have set my GsonJsonConverterImplementation to work with.目标是此方法应该能够与我设置我的 GsonJsonConverterImplementation 使用的任何类型一起使用。 Unfortunately, gson.fromJson(jsonString, T) does not work, nor does using T.class in place of T. I am sure the issue stems from my lack of understanding of Java generic types.不幸的是, gson.fromJson(jsonString, T)不起作用,使用T.class代替 T 也不起作用。我确信这个问题源于我对 Java 泛型类型缺乏理解。 What is the correct way of using a generic with Gson?在 Gson 中使用泛型的正确方法是什么?

Edit编辑
Using Kris's answer I would assume that this should work.使用克里斯的回答,我认为这应该有效。 Unfortunately, clazz cannot be used in this manner and causes a compiler error.不幸的是,clazz 不能以这种方式使用并导致编译器错误。 What are my options for working with a collection and a generic type with Gson?使用 Gson 处理集合和泛型类型时,我有哪些选择?

public List<T> deserializeList(String jsonString, Class<T> clazz) {
    GsonBuilder builder = new GsonBuilder();
    builder.setDateFormat("MM/dd/yy HH:mm:ss");
    Gson gson = builder.create();

    Type listType = new TypeToken<clazz>(){}.getType(); // compiler error

    return gson.fromJson(jsonString, listType);
}

The simplest approach for what you are attempting is to define the type of class which is to be returned in the method signature itself. 您尝试的最简单的方法是定义要在方法签名本身中返回的类的类型。 You can do so by either passing an instance of 'T' to the method or the Class of the value to be returned. 您可以通过将'T'实例传递给方法或将要返回的值的Class传递给它。 The second approach is the more typical in cases where you expect to generate a return value. 第二种方法是在您希望生成返回值的情况下更典型。 Here is an example of this approach using Gson: 以下是使用Gson的这种方法的示例:

public <T> T deserialize(String jsonString, Class<T> clazz) {
    GsonBuilder builder = new GsonBuilder();
    builder.setDateFormat("MM/dd/yy HH:mm:ss");

    Gson gson = builder.create();
    return gson.fromJson(jsonString, clazz);
}

Usage: 用法:

MyClass mc = deserialize(jsonString, MyClass.class);

To get the runtime type of List<T> , given the class of T , it would suck because JDK didn't think we need it so there's no support. 要获得运行时类型List<T>给定类的, T ,就吮吸,因为JDK不认为我们需要它,所以没有支持。 You can subclass ParameterizedType , but it really sucks. 你可以继承ParameterizedType ,但它真的很糟糕。

    Type typeListT = new ParameterizedType()
    {
        public Type[] getActualTypeArguments()
        {
            return new Type[]{clazz};
        }
        public Type getRawType()
        {
            return List.class;
        }
        public Type getOwnerType()
        {
            return null;
        }
        public boolean equals(Object obj)
        {
            // must implement equals per spec. this sucks
        }
        public int hashCode()
        {
            // this blows! Java forgot to specific it!
            // since we override equals, we should override hashCode
            // we have no idea what value should be returned here!
            // note we are co-existing with other ParameterizedType impls
        }
    };

I am using these method to read & write Object using GSON. 我正在使用这些方法使用GSON读写Object。

public static <T> void saveAnyTypeOfObject(String key, T value){
        Gson gson = new Gson();
        String json = gson.toJson(value);
        SharedPref.save(key, json);
    }
    //Type listType = new TypeToken<YourClass>(){}.getType();
    public static <T> T readAnyTypeOfObject(String key, Type tt) {
        Gson gson = new Gson();
        String json = SharedPref.read(key, "{}");
        T obj = gson.fromJson(json, tt);
        return obj;
    }

read it like 读它就像

  TypeToken<YourClassName> typeToken= new TypeToken<YourClassName>() {};
  YourClassName yourClassName = ListSharedPref.readAnyTypeOfObject("keyForSavingClass", typeToken.getType());

and save it like 并保存它

YourClassName yourClassName = gson.fromJson(objJsonObject.toString(),YourClassName.class);               
ListSharedPref.saveAnyTypeOfObject("keyForSavingClass",yourClassName);

If you have serialized a generic object like GenericClass<T> While deserializing you should provide a wrapper class with exact type for example:如果你已经序列化了一个像GenericClass<T>这样的通用对象,那么在反序列化时你应该提供一个具有精确类型的包装类,例如:

public class WrapperClass extends GenericClass<Integer>{
// body is not required
}

then you can call:然后你可以打电话:

GsonInstance.fromJson(string, WrapperClass.class);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM