Deserializing Generic Types with GSON

前端 未结 5 2026
耶瑟儿~
耶瑟儿~ 2020-11-27 14:46

I have some problems with implementation of Json Deserialization in my Android application (with Gson library)

I\'ve made class like this

public clas         


        
相关标签:
5条回答
  • 2020-11-27 14:52

    For anyone struggling with Kotlin like I did, I've found this way to work

    val type = object : TypeToken<MyJson<MyObject>>() { }.type
    val response = gson.fromJson<MyJson<MyObject>>(reader, type)
    

    Note that calling a generic function requires the type arguments at the call site after the name of the function (seen here)

    0 讨论(0)
  • 2020-11-27 14:54

    You have to specify the type of T at the time of deserialization. How would your List of posts get created if Gson didn't know what Type to instantiate? It can't stay T forever. So, you would provide the type T as a Class parameter.

    Now assuming, the type of posts was String you would deserialize MyJson<String> as (I've also added a String json parameter for simplicity; you would read from your reader as before):

    doInBackground(String.class, "{posts: [\"article 1\", \"article 2\"]}");
    
    protected MyJson<T> doInBackground(Class<T> type, String json, Void... params) {
    
        GsonBuilder gson = new GsonBuilder();
        Type collectionType = new TypeToken<MyJson<T>>(){}.getType();
    
        MyJson<T> myJson = gson.create().fromJson(json, collectionType);
    
        System.out.println(myJson.getPosts()); // ["article 1", "article 2"]
        return myJson;
    }
    

    Similarly, to deserialize a MyJson of Boolean objects

    doInBackground(Boolean.class, "{posts: [true, false]}");
    
    protected MyJson<T> doInBackground(Class<T> type, String json, Void... params) {
    
        GsonBuilder gson = new GsonBuilder();
        Type collectionType = new TypeToken<MyJson<T>>(){}.getType();
    
        MyJson<T> myJson = gson.create().fromJson(json, collectionType);
    
        System.out.println(myJson.getPosts()); // [true, false]
        return myJson;
    }
    

    I've assumed MyJson<T> for my examples to be as

    public class MyJson<T> {
    
        public List<T> posts;
    
        public List<T> getPosts() {
            return posts;
        }
    }
    

    So, if you were looking for to deserialize a List<MyObject> you would invoke the method as

    // assuming no Void parameters were required
    MyJson<MyObject> myJson = doInBackground(MyObject.class);
    
    0 讨论(0)
  • 2020-11-27 15:06

    So the above answer didn't work for me, after trial and error that's how my code ended:

    public class AbstractListResponse<T> {
        private List<T> result;
    
        public List<T> getResult() {
            return this.result;
        }
    }
    

    The important part here is the method signature, including the '< T >' on the left.

    protected <T> AbstractListResponse<T> parseAbstractResponse(String json, TypeToken type) {
        return new GsonBuilder()
                .create()
                .fromJson(json, type.getType());
    }
    

    When calling Gson, the method receives the TypeToken of the generic object.

    TypeToken<AbstractListResponse<MyDTO>> typeToken = new TypeToken<AbstractListResponse<MyDTO>>() {};
    AbstractListResponse<MyDTO> responseBase = parseAbstractResponse(json, typeToken);
    

    And finally the TypeToken can use MyDTO, or even a simple object, just MyDTO.

    0 讨论(0)
  • 2020-11-27 15:11

    Have you tried?

    gson.create().fromJson(reader, MyJson.class);
    

    EDIT

    After reading this post it seems that you use of Type is correct. I believe your issue is the use of T. You must remember that with Java there is type-erasure. This means that at runtime all instances of T are replaced with Object. Therefore at runtime what you are passing GSON is really MyJson<Object>. If you tried this with a concrete class in place of <T> I believe it would work.

    Google Gson - deserialize list<class> object? (generic type)

    0 讨论(0)
  • 2020-11-27 15:15

    If you are using gson 2.8.0 or higher, you can use the following method TypeToken#getParametized((Type rawType, Type... typeArguments))

    Example:

    protected MyJson<T> doInBackground(Class<T> type, String json, Void... params) {
    
        GsonBuilder gson = new GsonBuilder();
        Type collectionType = TypeToken.getParameterized(MyJson.class, type).getType();
    
        MyJson<T> myJson = gson.create().fromJson(json, collectionType);
    
        System.out.println(myJson.getPosts()); // [true, false]
        return myJson;
    }
    

    I believe this would work in your case.

    Credits to this answer.

    0 讨论(0)
提交回复
热议问题