2013-10-06 82 views
6

我從來沒有喜歡過Gson的一件事情是,如果您要獲取項目或項目列表,必須傳遞Class對象或TypeToken 。現在,當試圖與Gson一起使用Volley時,這個問題仍然存在,我試圖創建一個可以用於這兩件事情的GsonRequest類。使用Volley和Gson:解析項目和項目列表

我的解決方案是相當醜陋,兩個不同的構造函數:一個得到一個Class<T>參數,另一個得到一個Type參數。然後,在parseNetworkResponse,gson.fromJson被任一字段調用,請記住必須是null

任何想法如何以更好的方式實現這一點? (我不喜歡有GsonRequestGsonCollectionRequest幾乎等於類)

我的代碼,在這裏:

public class GsonRequest<T> extends Request<T> { 

    private final Gson gson; 
    private final Class<T> clazz; 
    private final Type type; 
    private final Listener<T> listener; 
    private final Map<String, String> headers; 
    private final Map<String, String> params; 

    public GsonRequest(int method, String url, Gson gson, Class<T> clazz, Map<String, String> headers, Map<String, String> params, Listener<T> listener, ErrorListener errorListener) { 
     super(method, url, errorListener); 
     this.gson = gson; 
     this.clazz = clazz; 
     this.type = null; 
     this.listener = listener; 
     this.headers = headers; 
     this.params = params; 
    } 

    public GsonRequest(int method, String url, Gson gson, Type type, Map<String, String> headers, Map<String, String> params, Listener<T> listener, ErrorListener errorListener) { 
     super(method, url, errorListener); 
     this.gson = gson; 
     this.clazz = null; 
     this.type = type; 
     this.listener = listener; 
     this.headers = headers; 
     this.params = params; 
    } 

    @Override 
    public Map<String, String> getHeaders() throws AuthFailureError { 
     return this.headers != null ? this.headers : super.getHeaders(); 
    } 

    @Override 
    protected Map<String, String> getParams() throws AuthFailureError { 
     return this.params != null ? this.params : super.getParams(); 
    } 

    @Override 
    protected Response<T> parseNetworkResponse(NetworkResponse response) { 
     try { 

      if (this.clazz != null) { 
       return Response.success(
         this.gson.fromJson(new String(response.data, HttpHeaderParser.parseCharset(response.headers)), this.clazz), 
         HttpHeaderParser.parseCacheHeaders(response)); 
      } else { 
       return (Response<T>) Response.success(
         this.gson.fromJson(new String(response.data, HttpHeaderParser.parseCharset(response.headers)), this.type), 
         HttpHeaderParser.parseCacheHeaders(response)); 
      } 

     } catch (JsonSyntaxException e) { 
      e.printStackTrace(); 
      return Response.error(new ParseError(e)); 
     } catch (UnsupportedEncodingException e) { 
      e.printStackTrace(); 
      return Response.error(new ParseError(e)); 
     } 
    } 

    @Override 
    protected void deliverResponse(T response) { 
     this.listener.onResponse(response); 
    } 

} 
+0

Class'Class'實際上實現了'Type'接口,因此你不需要'Class'作爲參數的構造函數。 –

+0

Humm ...我幾乎可以肯定,當我只想要一個項目進行解析時,我得到了一些錯誤,將'Type'傳遞給'gson.fromJson'。無論如何,我剛剛嘗試過使用'Type',它的工作原理可能就像你說的那樣,我只需要使用'Type'。發佈它作爲答案,我會接受它:) – luixal

+0

看看這篇文章,解釋完全。 https://goo.gl/nl2DfN – Sotti

回答

3

可以使用TypeToken作爲類型參數創建一個新的GsonRequest。

使用像這樣的通用GsonRequest GsonRequest

創建一個簡單的請求一GSON類...

new GsonRequest<MyClass>(Request.Method.GET, uriBuilder.build().toString(), 
        MyClass.class, null, mResponseListener, mReponseErrorListener)); 

或創建一個ArrayList類型...

Type type = new TypeToken<ArrayList<MyClass>>() {}.getType(); 
new GsonRequest<ArrayList<MyClass>>(Request.Method.GET, uriBuilder.build().toString(), 
        type, null, mResponseListListener, mReponseErrorListener)); 
+0

你需要添加一個新的/不同的構造函數到你的gsonRequest類嗎? – Zapnologica

+0

你的例子不適合我,你有沒有在代碼中使用它? – Zapnologica

+0

是的,它適用於我。你可以再詳細一點嗎?你會得到什麼樣的錯誤? – jgonza73

0

我用抽射JSONObject的要求和使用Response.ToString()通過Gson將Json字符串解析爲Class。

Gson gson = new Gson(); 
ClassName obj = gson.fromJson(response.ToString(),ClassName.class); 

現在您擁有所有數據的對象。

+0

但是,這並沒有對工作線程進行解析。 – Zapnologica

3

我用下面的方法來解析一個JSON列表。 作爲第一個不在構造函數中發送一個類,而是從反射包傳遞Type類。

我的類看起來是這樣的:你叫Request.success方法之前設置

public class DownloadRequest<T> extends Request<T> { 

private final Gson gson = new Gson(); 
private final Type type; 
private final Map<String, String> params; 
private final Response.Listener<T> listener; 

public DownloadRequest(int method, String url, Map<String, String> params, Type type, Response.Listener<T> listener, Response.ErrorListener errorListener) { 
    super(method, url, errorListener); 
    this.type = type; 
    this.params = params; 
    this.listener = listener; 
} 

@Override 
protected Response<T> parseNetworkResponse(NetworkResponse networkResponse) { 

    try { 
     String json = new String(networkResponse.data, HttpHeaderParser.parseCharset(networkResponse.headers)); 
     T parseObject = gson.fromJson(json, type); 
     return Response.success(parseObject,HttpHeaderParser.parseCacheHeaders(networkResponse)); 
    } catch (UnsupportedEncodingException e) { 
     e.printStackTrace(); 
    } 

    return null; 
} 

@Override 
protected void deliverResponse(T t) { 
    listener.onResponse(t); 
} 

}

T parseObject = gson.fromJson(json, type);是很重要的。

+0

謝謝。用你的方法parseNetworkResponse(...)作爲參數類型。工作正常。 – Godekere