2014-09-29 19 views
5

Sto lavorando con un'API REST che restituisce un documento JSON che inizia come segue e include una "raccolta" di elementi con ID di stringa come "ABC". Notare il campo "percorsi", che contiene una serie di campi chiamati "ABC", "ABD", "ABE", ecc, tuttavia percorsi non è rappresentato come un array in JSON, così tutti questiAnalizza manualmente parte di una risposta quando si utilizza Retrofit

{ 
"status":true, 
"page":1, 
"per_page":500, 
"total_count":1234, 
"total_pages":8, 
"total_on_page":500, 
"routes":{ 
    "ABC":[ 
    { 
     "value":22313, 
     <......> 

I sto usando Retrofit e il problema è che il campo dei percorsi non è un array (nonostante concettualmente lo sia certamente) e Retrofit/Gson mi richiedono di creare un oggetto modello per i percorsi con i campi vars abc, abd, etc - questo non è pratico mentre i dati cambiano. Per vari motivi, la modifica dell'API del server è difficile, quindi cerco di aggirare il problema sul client Android.

immagino questi sono mangiare:

  • intercettazione documento JSON prima che raggiunga GSON e modificare il documento, possibilmente con un parser GSON personalizzato, o intercettando la risposta HTTP.

  • Bypass il parsing JSON, e di acquisire il documento JSON da Retrofit (devo ancora capire come fare questo, o se è possibile)

  • Uso qualche caratteristica di retrofit sono a conoscenza di per mappare i nomi dei campi in una raccolta.

Apprezzerei molto l'aiuto, soprattutto se c'è un modo semplice e veloce per risolvere questo problema.

risposta

8

Si scopre che l'uso di retrofit di GSON di default rende abbastanza facile aggiungere un deserialiser personalizzato per gestire il parte del documento JSON che rappresentava il problema.

RestAdapter restAdapter = new RestAdapter.Builder() 
     .setEndpoint(ApiDefinition.BASE_URL) 
     .setConverter(getGsonConverter()) 
     .build(); 

public Converter getGsonConverter() { 
    Gson gson = new GsonBuilder() 
      .registerTypeAdapter(RouteList.class, new RouteTypeAdapter()) 
      .create(); 
    return new GsonConverter(gson); 
} 


public class RouteTypeAdapter implements JsonDeserializer<RouteList> { 
    @Override 
    public RouteList deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 
     Gson gson = new Gson(); 
     RouteList routeList = new RouteList(); 
     JsonObject jsonObject = json.getAsJsonObject(); 
     for (Map.Entry<String,JsonElement> elementJson : jsonObject.entrySet()){ 
      RouteList wardsRoutes = gson.fromJson(elementJson.getValue().getAsJsonArray(), RouteList.class); 
      routeList.addAll(wardsRoutes); 
     } 
     return routeList; 
    } 

} 
+1

Lo stavo cercando da così tanto tempo ... Questo è il modo pulito per farlo, grazie! – MathieuMaree

+0

che cos'è ApiDefinition.BASE_URL? –

+0

Come usare questo? –

2

Dopo aver chiamato RestService, non utilizzare Nome modello come argomento, è necessario utilizzare la classe predefinita Response dalla libreria di aggiornamento.

RestService Metodo

@FormUrlEncoded 
    @POST(GlobalVariables.LOGIN_URL) 
    void Login(@Field("email") String key, @Field("password") String value, Callback<Response> callback); 

metodo di chiamata in attività

getService().Login(email, password, new MyCallback<Response>(context, true, null) 
{ 
    @Override 
    public void failure(RetrofitError arg0) 
    { 
     // TODO Auto-generated method stub 
     UtilitySingleton.dismissDialog((BaseActivity<?>) context); 
     System.out.println(arg0.getResponse()); 
     } 

    @Override 
    public void success(Response arg0, Response arg1) 
    { 
     String result = null; 
     StringBuilder sb = null; 
     InputStream is = null; 
     try 
     { 
       is = arg1.getBody().in(); 
       BufferedReader reader = new BufferedReader(new InputStreamReader(is)); 
       sb = new StringBuilder(); 
       String line = null; 
       while ((line = reader.readLine()) != null) 
       { 
        sb.append(line + "\n"); 
        result = sb.toString(); 
        System.out.println("Result :: " + result); 
       } 
      } 
      catch (Exception e) 
      { 
       e.printStackTrace(); 
      } 
     } 
    }); 
+1

Il deserializzatore di scrittura è molto più pulito. Anche l'analisi viene eseguita sul thread in background, a differenza del tuo approccio. :) –

+0

Questa non è una buona idea. – Gunhan

Problemi correlati