2014-10-05 157 views
5

在Android應用程序中工作時,我想要製作一個最終的泛型方法來發送HTTP請求(使用loopj)並反序列化它們(使用Gson)時遇到了問題。Gson fromJson反序列化泛型

正如你可以同時使用gson.fromJson知道你不能這樣做:

gson.fromJson(responseBody, new TypeToken<T>() {}.getType()); 

gson.fromJson(responseBody, new TypeToken<ArrayList<T>>() {}.getType()) 

而是實際對象(或在第二種情況實際對象的列表),你已經通過爲T,您將獲得LinkedTreeMap對象(或對象列表LinkedTreeMap)。

如果您想要仍然想反序列化泛型類型對象(-s),請參閱下面的答案。

+獎金:

http://blog.xebia.com/2009/02/07/acessing-generic-types-at-runtime-in-java/

How to get concrete type of a generic interface

Java Type Generic as Argument for GSON

回答

5

反序列化JSON對象:用於循環J + GSON

感謝這些帖子的作者和評論者最終的通用解決方案到泛型類型的java對象

首先我們需要得到實際類別的泛型T

我們可以通過傳遞類本身(Class<T> cl)或通過從具有泛型類型的對象(SomeObject<T> someObjectWithGenericType)中獲取類來完成。我將在例子中使用第二種情況。

然後我們需要創建一個類Element<T>的特殊對象,它會告訴Gson什麼類用於反序列化。

public <T> T getObject(String json, SomeObject<T> someObjectWithGenericType) { 
    Class cl = getTypeClassOfObject(someObjWithGenericType); 
    T object = gson.fromJson(json, new Element<T>(cl)); 
    return object; 
} 

private Class getTypeClassOfObject(Object obj) { 
    return (Class) ((ParameterizedType) obj.getClass().getGenericSuperclass()).getActualTypeArguments()[0]; 
} 

private class Element<T> implements ParameterizedType { 

    private Class<T> cl; 

    public Element(Class<T> cl) { 
     this.cl = cl; 
    } 

    public Type[] getActualTypeArguments() { 
     return new Type[] {cl}; 
    } 

    public Type getRawType() { 
     return cl; 
    } 

    public Type getOwnerType() { 
     return null; 
    } 
} 

如果您SomeObject<T>是一個接口(可能是一個回調,因爲你將在循環J例子在後面看到),你可以改用這種方法的getTypeClassOfObject

private Class getTypeClassOfInterfaceObject(Object obj) { 
    return (Class) ((ParameterizedType) obj.getClass().getGenericInterfaces()[0]).getActualTypeArguments()[0]; 
} 

反序列化JSON數組列表泛型類型的java對象

同樣的想法,但我們有一個不同的特殊類來幫助Gson反序列化:

public <T> List<T> getList(String json, SomeObject<T> someObjectWithGenericType) { 
    Class cl = getTypeClassOfObject(someObjWithGenericType); 
    List<T> list = gson.fromJson(json, new ListWithElements<T>(cl)); 
    return list; 
} 

private class ListWithElements<T> implements ParameterizedType { 

    private Class<T> elementsClass; 

    public ListWithElements(Class<T> elementsClass) { 
     this.elementsClass = elementsClass; 
    } 

    public Type[] getActualTypeArguments() { 
     return new Type[] {elementsClass}; 
    } 

    public Type getRawType() { 
     return List.class; 
    } 

    public Type getOwnerType() { 
     return null; 
    } 
} 

BONUS

正如你會在這裏看到someObjectWithGenericType將是與泛型類型T回調。 儘管我使用loopj,但我確定可以使用任何其他異步http客戶端來實現相同的結果。

循環J + GSON泛型:對象

public <T> void getObject(String url, HashMap<String, String> paramsMap, final GetObjectCallback<T> callback) { 
    RequestParams params = convertParams(paramsMap); 
    client.get(url, params, new TextHttpResponseHandler() { 
     @Override 
     public void onSuccess(int statusCode, Header[] headers, String responseBody) { 
      try { 
       Class cl = getTypeClassOfInterfaceObject(callback); 
       T object = gson.fromJson(responseBody, new Element<T>(cl)); 
       if (object != null) { 
        callback.onSuccess(object); 
       } else { 
        callback.onFailure(); 
       } 
      } catch (Exception e) { 
       e.printStackTrace(); 
       callback.onFailure(); 
      } 
     } 

     @Override 
     public void onFailure(int statusCode, Header[] headers, String responseBody, Throwable error) { 
      error.printStackTrace(); 
      callback.onFailure(); 
     } 
    }); 
} 

private RequestParams convertParams(HashMap<String, String> paramsMap) { 
    RequestParams params = new RequestParams(); 
    if (paramsMap != null) { 
     for (String key : paramsMap.keySet()) { 
      params.put(key, paramsMap.get(key)); 
     } 
    } 
    return params; 
} 

public interface GetObjectCallback<T> { 
    void onSuccess(T item); 
    void onFailure(); 
} 

循環J + GSON泛型:列表

public <T> void getList(String url, HashMap<String, String> paramsMap, final GetListCallback<T> callback) { 
    RequestParams params = convertParams(paramsMap); 
    client.get(url, params, new TextHttpResponseHandler() { 
     @Override 
     public void onSuccess(int statusCode, Header[] headers, String responseBody) { 
      try { 
       Class cl = getTypeClassOfInterfaceObject(callback); 
       List<T> list = gson.fromJson(responseBody, new ListWithElements<T>(cl)); 
       if (list != null) { 
        callback.onSuccess(list); 
       } else { 
        callback.onFailure(); 
       } 
      } catch (Exception e) { 
       e.printStackTrace(); 
       callback.onFailure(); 
      } 
     } 

     @Override 
     public void onFailure(int statusCode, Header[] headers, String responseBody, Throwable error) { 
      error.printStackTrace(); 
      callback.onFailure(); 
     } 
    }); 
} 

public interface GetListCallback<T> { 
    void onSuccess(List<T> list); 
    void onFailure(); 
} 

用法:對象

api.getObject(URL, paramsMap, new GetObjectCallback<NewsItem>() { 
    @Override 
    public void onSuccess(NewsItem item) { 
     // do something 
    } 

    @Override 
    public void onFailure() { 
     // do something 
    } 
}); 

用法:列表

api.getList(URL, paramsMap, new GetListCallback<Comment>() { 
    @Override 
    public void onSuccess(List<Comment> list) { 
     // do something 
    } 

    @Override 
    public void onFailure() { 
     // do something 
    } 
}); 

任何改進都非常歡迎!