Retrofit 2 的自定义转换器
Custom converter for Retrofit 2
我必须处理动态 JSON 响应。
之前,我使用 classes 和注释如下:
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;
}
}
当状态为 1(成功)时,onResponse
被触发,我可以获得 ChatResponse 对象。但是,当状态为 0 时,JSON 表示中的响应为假并且失败(onFailure
被触发)。
我想创建自定义转换器,this question 有一个很好的示例,但该示例是针对 Retrofit 1 的。
I have to 创建一个扩展 Converter.Factory
的 class,但我不知道如何覆盖此 class 的方法。
其实我有下一个:
@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);
}
此时我如何自己解析 JSON 响应?
提前致谢。
我正在寻找一个关于如何为 Retrofit 2 实现自定义转换器的简单示例。不幸地找到了 none。
我找到了 this example,但至少对我来说,它太复杂了,无法达到我的目的。
幸运的是,我找到了解决办法。
这个方案是用GSON deserializers
.
我们不需要创建自定义转换器,我们只需要自定义 GSON converter
。
这是一个很棒的tutorial。这是我用来解析问题中描述的 JSON 的代码:
Login Deserializer:定义如何将 JSON 解析为目标 class 的对象(使用条件和任何我们需要的)。
Custom GSON converter:构建一个使用我们自定义解串器的 GSON 转换器。
为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();
}
在你想去的地方像这样打电话
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());
}
});
请求和响应的两个文件是
文档名
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
您可以使用 http://www.jsonschema2pojo.org/ 将您的 JSON 转换为以下书面格式,方法是选择 SourceType:JSON 和 Annotation Style: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;
}
}
}
我发现@JCarlos 的解决方案准确、快速且正确。我需要在 Android 上为 Retrofit 2 实施 自定义日期转换器。看来你需要在 GSonConverterFactory 中注册一个新的类型序列化器。实现是在 Kotlin 语言中完成的。
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)
}
}
和注册:
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()
}
Here就是一个例子。
很快:
Gson gson = new GsonBuilder()
.registerTypeAdapter(MyClass.class, new MyClassTypeAdapter())
.create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com")
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
我必须处理动态 JSON 响应。
之前,我使用 classes 和注释如下:
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;
}
}
当状态为 1(成功)时,onResponse
被触发,我可以获得 ChatResponse 对象。但是,当状态为 0 时,JSON 表示中的响应为假并且失败(onFailure
被触发)。
我想创建自定义转换器,this question 有一个很好的示例,但该示例是针对 Retrofit 1 的。
I have to 创建一个扩展 Converter.Factory
的 class,但我不知道如何覆盖此 class 的方法。
其实我有下一个:
@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);
}
此时我如何自己解析 JSON 响应?
提前致谢。
我正在寻找一个关于如何为 Retrofit 2 实现自定义转换器的简单示例。不幸地找到了 none。
我找到了 this example,但至少对我来说,它太复杂了,无法达到我的目的。
幸运的是,我找到了解决办法。
这个方案是用GSON deserializers
.
我们不需要创建自定义转换器,我们只需要自定义 GSON converter
。
这是一个很棒的tutorial。这是我用来解析问题中描述的 JSON 的代码:
Login Deserializer:定义如何将 JSON 解析为目标 class 的对象(使用条件和任何我们需要的)。
Custom GSON converter:构建一个使用我们自定义解串器的 GSON 转换器。
为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();
}
在你想去的地方像这样打电话
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());
}
});
请求和响应的两个文件是
文档名
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 您可以使用 http://www.jsonschema2pojo.org/ 将您的 JSON 转换为以下书面格式,方法是选择 SourceType:JSON 和 Annotation Style: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;
}
}
}
我发现@JCarlos 的解决方案准确、快速且正确。我需要在 Android 上为 Retrofit 2 实施 自定义日期转换器。看来你需要在 GSonConverterFactory 中注册一个新的类型序列化器。实现是在 Kotlin 语言中完成的。
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)
}
}
和注册:
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()
}
Here就是一个例子。
很快:
Gson gson = new GsonBuilder()
.registerTypeAdapter(MyClass.class, new MyClassTypeAdapter())
.create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com")
.addConverterFactory(GsonConverterFactory.create(gson))
.build();