2013-06-27 1 views
4

Je souhaite créer une implémentation JacksonJSONRequest dans Volley. Mes demandes/réponses comme la plupart ont un objet de requête de type X, et un objet de réponse de type Y.Création d'une requête Jackson analysée dans Volley

Le Volley demande classe de base définit à la fois comme le même ...

public class JacksonRequest<T> extends Request<T> 
... 
protected Response<T> parseNetworkResponse(NetworkResponse response) 

Ce n » J'ai beaucoup de sens pour moi. Je ne peux pas imaginer beaucoup de demandes REST utilisant la même structure pour la demande et les réponses.

Est-ce que je manque quelque chose d'évident ici?

Répondre

4

Voici ma mise en œuvre ...

public class JacksonRequest<T> extends JsonRequest<T> 
{ 
    private Class<T> responseType; 

    /** 
    * Creates a new request. 
    * 
    * @param method 
    *   the HTTP method to use 
    * @param url 
    *   URL to fetch the JSON from 
    * @param requestData 
    *   A {@link Object} to post and convert into json as the request. Null is allowed and indicates no parameters will be posted along with request. 
    * @param listener 
    *   Listener to receive the JSON response 
    * @param errorListener 
    *   Error listener, or null to ignore errors. 
    */ 
    public JacksonRequest(int method, String url, Object requestData, Class<T> responseType, Listener<T> listener, ErrorListener errorListener) 
    { 
     super(method, url, (requestData == null) ? null : Mapper.string(requestData), listener, errorListener); 
     this.responseType = responseType; 
    } 

    @Override 
    protected Response<T> parseNetworkResponse(NetworkResponse response) 
    { 
     try 
     { 
      String jsonString = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); 
      return Response.success(Mapper.objectOrThrow(jsonString, responseType), HttpHeaderParser.parseCacheHeaders(response)); 
     } 
     catch (Exception e) 
     { 
      return Response.error(new ParseError(e)); 
     } 
    } 
} 

La classe Mapper dont les utilisations ci-dessus est juste une petite classe wrapper ...

/** 
* Singleton wrapper class which configures the Jackson JSON parser. 
*/ 
public final class Mapper 
{ 
    private static ObjectMapper MAPPER; 

    public static ObjectMapper get() 
    { 
     if (MAPPER == null) 
     { 
      MAPPER = new ObjectMapper(); 

      // This is useful for me in case I add new object properties on the server side which are not yet available on the client. 
      MAPPER.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false); 
     } 

     return MAPPER; 
    } 

    public static String string(Object data) 
    { 
     try 
     { 
      return get().writeValueAsString(data); 
     } 
     catch (Exception e) 
     { 
      e.printStackTrace(); 
      return null; 
     } 
    } 

    public static <T> T objectOrThrow(String data, Class<T> type) throws JsonParseException, JsonMappingException, IOException 
    { 
     return get().readValue(data, type); 
    } 

    public static <T> T object(String data, Class<T> type) 
    { 
     try 
     { 
      return objectOrThrow(data, type); 
     } 
     catch (Exception e) 
     { 
      e.printStackTrace(); 
      return null; 
     } 
    } 
} 
0

Je ne sais pas cela va vous aider, mais j'ai une demande jackson qui prennent un type et renvoie une chaîne, je l'utilise parce que la plupart de mes demandes juste retour un en-tête

Modifier

il a différents types de demande et de réponse, il est pas super élégant mais il fonctionne

public class JacksonJsonRequest<K, T> extends Request<T> { 

private ObjectMapper mMapper = new ObjectMapper(); 

private static final String PROTOCOL_CHARSET = "utf-8"; 


private static final String PROTOCOL_CONTENT_TYPE = 
     String.format("application/json; charset=%s", PROTOCOL_CHARSET); 

private final Response.Listener<T> mListener; 
private final K mRequestBody; 
private final Class<T> mClass; 
private final Map<String, String> mHeaders; 




public JacksonJsonRequest(int method, String url, K requestBody, 
          Response.ErrorListener errorListener, Response.Listener<T> listener, 
          Map<String, String> headers, Class<T> claz) { 
    super(method, url, errorListener); 

    mListener = listener; 
    mRequestBody = requestBody; 
    mHeaders = headers; 
    mClass = claz; 

} 

@Override 
protected Response<T> parseNetworkResponse(NetworkResponse networkResponse) { 
    String jsonString = new String(networkResponse.data); 
    try { 
     T result = mMapper.readValue(jsonString, mClass); 
     return Response.success(result, HttpHeaderParser.parseCacheHeaders(networkResponse)); 
    } catch (IOException e) { 
     Log.e("jacksontest", "error parsing", e); 
    } 
    return null; 
} 

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

@Override 
public String getBodyContentType() { 
    return PROTOCOL_CONTENT_TYPE; 
} 

@Override 
public byte[] getBody() { 
    try { 
     return mRequestBody == null ? null : mMapper.writeValueAsBytes(mRequestBody); 
    } catch (JsonProcessingException e) { 
     Log.e("Jacksontest", "error parsing", e); 
    } 
    return null; 
} 

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

}

+0

Merci pour votre message, mais je suis à la recherche d'un moyen de spécifiez les types d'objet requête et réponse, par opposition à l'attente d'une chaîne. Des frameworks similaires tels que RoboSpice gèrent cela dans la boîte. Je suis juste surpris que Volley ne vous autorise pas (du moins autant que je puisse le voir) à définir les types Req/Res lors d'une requête. Je peux imaginer que cela viendra à mesure que Volley arrive à maturité. –

+0

J'ai édité ma réponse, je ne sais pas si c'est la voie à suivre, mais cela fonctionne – alex

+0

Je cherchais quelque chose comme ça, mais y a deux types de réponse sur mi API, une avec le bon type json, et une autre avec une erreur tapez comme {"erreur:" "INVALID_CREDENTIAL"}. Je gère cela avec statusCode, mais sur de minuscules cas, j'ai un statusCode et plusieurs raisons. –

Questions connexes