2016-02-19 5 views
11

Je dois gérer des réponses JSON dynamiques.Convertisseur personnalisé pour Retrofit 2

Avant, j'utilisais des classes et des annotations comme suit:

public class ChatResponse { 

    @SerializedName("status") 
    private int status; 

    @SerializedName("error") 
    private String error; 

    @SerializedName("response") 
    private Talk response; 

    public int getStatus() { 
     return status; 
    } 

    public String getError() { 
     return error; 
    } 

    public Talk getResponse() { 
     return response; 
    } 
} 

Lorsque l'état est 1 (succès) le onResponse est tiré et je peux obtenir un objet ChatResponse. Mais, lorsque le statut est 0, la réponse est fausse dans la représentation JSON et elle échoue (onFailure est renvoyé).

Je veux créer mon convertisseur de mesure et this question a un bon exemple, mais cet exemple est MODIFIABLE 1.

I have to créer une classe qui étend Converter.Factory, mais je ne sais pas comment remplacer les méthodes de cette classe.

En fait, j'ai la prochaine:

@Override 
public Converter<ResponseBody, ?> fromResponseBody(Type type, Annotation[] annotations) { 

    return super.fromResponseBody(type, annotations); 
} 

@Override 
public Converter<?, RequestBody> toRequestBody(Type type, Annotation[] annotations) { 

    return super.toRequestBody(type, annotations); 
} 

Comment puis-je analyser la réponse JSON par moi-même à ce moment?

Merci d'avance.

Répondre

29

Je cherchais un exemple simple sur la façon de mettre en œuvre un convertisseur personnalisé pour Retrofit 2, et n'a rien trouvé de bon (there is an example mais, au moins pour moi, c'est trop compliqué pour mon purpouse).

Mais finalement, j'ai trouvé une solution. Cette solution est d'utiliser GSON deserializers. Nous n'avons donc pas besoin d'un convertisseur personnalisé, il suffit de personnaliser le GSON converter.

Voici un excellent tutorial. Et voici mon code pour analyser le JSON décrit dans ma question:

  • Login Deserializer: Définit comment analyser le JSON comme objet de notre classe cible (en utilisant conditionals et tout ce que nous avons besoin).
  • Custom GSON converter: Builds un convertisseur GSON qui utilise notre coutume désérialiseur
+0

Cela ajouterait une usine de conversion statique pour un même type de réponse. Que faire si je veux rendre l'analyse de différents objets de réponse optionnelle? J'ai peut-être varié des réponses pour divers apis avec des optionsl et des objets de réponses fixes. –

2

compiler ces deux bibliothèques pour retrofit2

compile 'com.squareup.retrofit2:retrofit:2.1.0' 
compile 'com.squareup.retrofit2:converter-gson:2.0.2' 


import com.lendingkart.prakhar.lendingkartdemo.retrofitPOJOResponse.DocsNameResponse; 
import com.lendingkart.prakhar.lendingkartdemo.retrofitrequests.DocName; 

import retrofit2.Call; 
import retrofit2.Retrofit; 
import retrofit2.converter.gson.GsonConverterFactory; 
import retrofit2.http.Body; 
import retrofit2.http.Multipart; 
import retrofit2.http.POST; 
import retrofit2.http.Part; 
import retrofit2.http.PartMap; 


    public interface APIInterface { 

     String ENDPOINT = "https://app.xxxxxxxxx.com/"; 


     @POST("lkart/api/docs") 
     Call<DocsNameResponse> DOCS_NAME_RESPONSE_CALL(@Body DocName docName); 



     public static final Retrofit retrofit = new Retrofit.Builder() 
       .baseUrl(APIInterface.ENDPOINT) 
       .addConverterFactory(GsonConverterFactory.create()) 
       .build(); 

    } 

appel comme ceux-ci où vous voulez

 String doc_name = "Loans/jdfjdanklnadkm;cnak_"; 
     APIInterface apiInterface = APIInterface.retrofit.create(APIInterface.class); 


    Call<DocsNameResponse> DocsCall = apiInterface.DOCS_NAME_RESPONSE_CALL(new DocName(doc_name)); 
     DocsCall.enqueue(new Callback<DocsNameResponse>() { 
      @Override 
      public void onResponse(Call<DocsNameResponse> call, Response<DocsNameResponse> response) { 
       Log.d("APIResult", String.valueOf(response.body().getData().get(3).getName())); 
      } 

      @Override 
      public void onFailure(Call<DocsNameResponse> call, Throwable t) { 
       Log.d("APIError", t.getMessage()); 
      } 
     }); 

et deux fichiers pour la demande et la réponse sont

DocName

public class DocName { 
    private String name; 

    public DocName(String name) { 
     this.name = name; 
    } 

    /** 
    * @return The name 
    */ 
    public String getName() { 
     return name; 
    } 

    /** 
    * @param name The name 
    */ 
    public void setName(String name) { 
     this.name = name; 
    } 

} 

DocNameResponse Vous pouvez utiliser http://www.jsonschema2pojo.org/ pour convertir votre JSON au format écrit ci-dessous en choisissant SourceType: JSON et Style Annotation: GSON

import com.google.gson.annotations.Expose; 
import com.google.gson.annotations.SerializedName; 



import java.util.List; 


public class DocsNameResponse { 

    @SerializedName("message") 
    @Expose 
    private String message; 
    @SerializedName("statusCode") 
    @Expose 
    private Integer statusCode; 
    @SerializedName("data") 
    @Expose 
    private List<Datum> data = null; 
    @SerializedName("list") 
    @Expose 
    private Object list; 
    @SerializedName("cscStatus") 
    @Expose 
    private Boolean cscStatus; 
    @SerializedName("status") 
    @Expose 
    private Object status; 
    @SerializedName("eligibleStatus") 
    @Expose 
    private Boolean eligibleStatus; 
    @SerializedName("pwd") 
    @Expose 
    private Object pwd; 
    @SerializedName("uname") 
    @Expose 
    private Object uname; 
    @SerializedName("assignedToList") 
    @Expose 
    private Object assignedToList; 

    /** 
    * @return The message 
    */ 
    public String getMessage() { 
     return message; 
    } 

    /** 
    * @param message The message 
    */ 
    public void setMessage(String message) { 
     this.message = message; 
    } 

    /** 
    * @return The statusCode 
    */ 
    public Integer getStatusCode() { 
     return statusCode; 
    } 

    /** 
    * @param statusCode The statusCode 
    */ 
    public void setStatusCode(Integer statusCode) { 
     this.statusCode = statusCode; 
    } 

    /** 
    * @return The data 
    */ 
    public List<Datum> getData() { 
     return data; 
    } 

    /** 
    * @param data The data 
    */ 
    public void setData(List<Datum> data) { 
     this.data = data; 
    } 

    /** 
    * @return The list 
    */ 
    public Object getList() { 
     return list; 
    } 

    /** 
    * @param list The list 
    */ 
    public void setList(Object list) { 
     this.list = list; 
    } 

    /** 
    * @return The cscStatus 
    */ 
    public Boolean getCscStatus() { 
     return cscStatus; 
    } 

    /** 
    * @param cscStatus The cscStatus 
    */ 
    public void setCscStatus(Boolean cscStatus) { 
     this.cscStatus = cscStatus; 
    } 

    /** 
    * @return The status 
    */ 
    public Object getStatus() { 
     return status; 
    } 

    /** 
    * @param status The status 
    */ 
    public void setStatus(Object status) { 
     this.status = status; 
    } 

    /** 
    * @return The eligibleStatus 
    */ 
    public Boolean getEligibleStatus() { 
     return eligibleStatus; 
    } 

    /** 
    * @param eligibleStatus The eligibleStatus 
    */ 
    public void setEligibleStatus(Boolean eligibleStatus) { 
     this.eligibleStatus = eligibleStatus; 
    } 

    /** 
    * @return The pwd 
    */ 
    public Object getPwd() { 
     return pwd; 
    } 

    /** 
    * @param pwd The pwd 
    */ 
    public void setPwd(Object pwd) { 
     this.pwd = pwd; 
    } 

    /** 
    * @return The uname 
    */ 
    public Object getUname() { 
     return uname; 
    } 

    /** 
    * @param uname The uname 
    */ 
    public void setUname(Object uname) { 
     this.uname = uname; 
    } 

    /** 
    * @return The assignedToList 
    */ 
    public Object getAssignedToList() { 
     return assignedToList; 
    } 

    /** 
    * @param assignedToList The assignedToList 
    */ 
    public void setAssignedToList(Object assignedToList) { 
     this.assignedToList = assignedToList; 
    } 


    public class Datum { 

     @SerializedName("id") 
     @Expose 
     private Object id; 
     @SerializedName("name") 
     @Expose 
     private String name; 
     @SerializedName("applicationId") 
     @Expose 
     private Object applicationId; 
     @SerializedName("userId") 
     @Expose 
     private Object userId; 
     @SerializedName("documentName") 
     @Expose 
     private String documentName; 
     @SerializedName("documentType") 
     @Expose 
     private Object documentType; 
     @SerializedName("freshloan") 
     @Expose 
     private Object freshloan; 

     /** 
     * @return The id 
     */ 
     public Object getId() { 
      return id; 
     } 

     /** 
     * @param id The id 
     */ 
     public void setId(Object id) { 
      this.id = id; 
     } 

     /** 
     * @return The name 
     */ 
     public String getName() { 
      return name; 
     } 

     /** 
     * @param name The name 
     */ 
     public void setName(String name) { 
      this.name = name; 
     } 

     /** 
     * @return The applicationId 
     */ 
     public Object getApplicationId() { 
      return applicationId; 
     } 

     /** 
     * @param applicationId The applicationId 
     */ 
     public void setApplicationId(Object applicationId) { 
      this.applicationId = applicationId; 
     } 

     /** 
     * @return The userId 
     */ 
     public Object getUserId() { 
      return userId; 
     } 

     /** 
     * @param userId The userId 
     */ 
     public void setUserId(Object userId) { 
      this.userId = userId; 
     } 

     /** 
     * @return The documentName 
     */ 
     public String getDocumentName() { 
      return documentName; 
     } 

     /** 
     * @param documentName The documentName 
     */ 
     public void setDocumentName(String documentName) { 
      this.documentName = documentName; 
     } 

     /** 
     * @return The documentType 
     */ 
     public Object getDocumentType() { 
      return documentType; 
     } 

     /** 
     * @param documentType The documentType 
     */ 
     public void setDocumentType(Object documentType) { 
      this.documentType = documentType; 
     } 

     /** 
     * @return The freshloan 
     */ 
     public Object getFreshloan() { 
      return freshloan; 
     } 

     /** 
     * @param freshloan The freshloan 
     */ 
     public void setFreshloan(Object freshloan) { 
      this.freshloan = freshloan; 
     } 

    } 

} 
1

J'ai trouvé @JCarlos solution pour être précis, rapide et correct.J'avais besoin de mettre en œuvre convertisseur de date personnalisé pour Retrofit 2 sur Android. Il semble que vous devez enregistrer un nouveau sérialiseur de type dans GSonConverterFactory. La mise en œuvre se fait au Kotlin lang.

class RetrofitDateSerializer : JsonSerializer<Date> { 
    override fun serialize(srcDate: Date?, typeOfSrc: Type?, context: JsonSerializationContext?): JsonElement? { 
     if (srcDate == null) 
      return null 
     val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss") 
     val formatted = dateFormat.format(srcDate) 
     return JsonPrimitive(formatted) 
    } 
} 

et l'inscription:

private fun buildGsonConverterFactory(): GsonConverterFactory { 
    val gsonBuilder = GsonBuilder() 
    // Custom DATE Converter for Retrofit 
    gsonBuilder.registerTypeAdapter(Date::class.java, RetrofitDateSerializer()) 
    return GsonConverterFactory.create(gsonBuilder.create()) 
} 

@Provides @Singleton 
internal fun providesRetrofit(applicationContext: Context): Retrofit { 
    return Retrofit.Builder() 
      .baseUrl(GluApp.Static.BASE_REST_URL_ADDR) 
      .addConverterFactory(
        buildGsonConverterFactory()) 
      .build() 
}