2016-02-19 12 views
11

Muszę obsłużyć dynamiczne odpowiedzi JSON.Niestandardowy konwerter dla Retrofit 2

Wcześniej używałem klasy i adnotacje w następujący sposób:

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; 
    } 
} 

Gdy stan jest 1 (sukces) onResponse wypala i mogę uzyskać obiekt ChatResponse. Jednak, gdy status wynosi 0, odpowiedź jest nieprawidłowa w reprezentacji JSON i nie powiedzie się (onFailure jest uruchamiany).

Chcę utworzyć mój własny konwerter i this question ma dobry przykład, ale ten przykład jest dla Retrofit 1.

I have to utworzyć klasę, która rozciąga Converter.Factory, ale nie wiem, w jaki sposób zastąpić metody tej klasy.

Właściwie mam następny:

@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); 
} 

Jak mogę analizować odpowiedzi JSON przez mój własny w tym momencie?

Z góry dziękuję.

Odpowiedz

29

Szukałem prostego przykładu, jak zaimplementować niestandardowy konwerter dla Retrofit 2 i nie znalazłem nic dobrego (there is an example, ale przynajmniej dla mnie to zbyt skomplikowane dla mojego celu).

Ale w końcu znalazłem rozwiązanie. To rozwiązanie polega na użyciu GSON deserializers. Więc nie potrzebujemy niestandardowego konwertera, musimy tylko dostosować GSON converter. To jest wspaniałe . I tu jest mój kod do analizowania JSON opisaną w moje pytanie:

  • Login Deserializer: określenie sposobu analizowania JSON jako obiekt naszej klasy docelowej (używając warunkowe i co trzeba).
  • Custom GSON converter: Buduje konwerter GSON który używa nasz zwyczaj Deserializator
+0

byłoby to dodać statyczną fabrykę Converter dla samego typu odpowiedzi. Co się stanie, jeśli chcę, aby parsowanie różnych obiektów odpowiedzi było opcjonalne? Mogłem mieć różne odpowiedzi dla różnych apisów z opcjami i stałymi obiektami odpowiedzi. –

2

skompilować te dwie biblioteki dla 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(); 

    } 

połączenia jak te, gdzie chcesz

 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()); 
      } 
     }); 

i dwóch plików dla żądania i odpowiedzi są

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 Można użyć http://www.jsonschema2pojo.org/ do konwersji do formatu JSON poniżej pisemnej wybierając SourceType: JSON i Adnotacja Styl: 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

znalazłem @JCarlos rozwiązanie jest precyzyjne, szybkie i poprawne.Musiałem wdrożyć niestandardowy konwerter daty dla Retrofit 2 na Androida. Wygląda na to, że musisz zarejestrować nowy serializator typów w GSonConverterFactory. Wdrażanie odbywa się w Kotlin język.

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) 
    } 
} 

i rejestracja:

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() 
} 
Powiązane problemy