在 Gson 中使用泛型类型

发布于 2024-10-24 17:50:54 字数 1210 浏览 2 评论 0原文

我正在尝试创建一个与 Google Gson 一起使用的通用类。我创建了类 GsonJsonConverterImplementation。此类具有以下方法:

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
}

目标是该方法应该能够与我设置的 GsonJsonConverterImplementation 所使用的任何类型一起使用。不幸的是, gson.fromJson(jsonString, T) 不起作用,使用 T.class 代替 T 也不起作用。我确信问题源于我缺乏理解Java 泛型类型。使用 Gson 泛型的正确方法是什么?

编辑
使用 Kris 的答案 我认为这应该可行。不幸的是,clazz 不能以这种方式使用,并且会导致编译器错误。使用 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);
}

I am trying to create a generic class for use with Google Gson. I've created the class 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. 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. What is the correct way of using a generic with 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. What are my options for working with a collection and a generic type with 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);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

独享拥抱 2024-10-31 17:50:54

对于您尝试的最简单的方法是定义要在方法签名本身中返回的类的类型。您可以通过将“T”的实例传递给方法或要返回值的类来实现此目的。在您希望生成返回值的情况下,第二种方法更为典型。以下是使用 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);
}

用法:

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

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. 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:

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);
Bonjour°[大白 2024-10-31 17:50:54

要获取 List 的运行时类型,给定 T 类,这会很糟糕,因为 JDK 认为我们不需要它,所以没有支持。您可以对 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
        }
    };

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. You can subclass ParameterizedType, but it really sucks.

    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
        }
    };
伤感在游骋 2024-10-31 17:50:54

我正在使用这些方法来阅读&使用 GSON 编写对象。

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;
    }

阅读它

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

并保存它

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

I am using these method to read & write Object using GSON.

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);
灯下孤影 2024-10-31 17:50:54

如果您序列化了一个通用对象,例如 GenericClass
在反序列化时,您应该提供一个具有确切类型的包装类,例如:

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

然后您可以调用:

GsonInstance.fromJson(string, WrapperClass.class);

If you have serialized a generic object like GenericClass<T>
While deserializing you should provide a wrapper class with exact type for example:

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

then you can call:

GsonInstance.fromJson(string, WrapperClass.class);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文