Retrofit 2的自定义转换器

26

我需要处理动态JSON响应。

以前,我使用以下类和注释:

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表示中响应为false,因此失败(触发onFailure)。
我想创建自定义转换器,这个问题有一个很好的例子,但是该示例适用于Retrofit 1。 我必须创建一个扩展Converter.Factory的类,但我不知道如何覆盖此类的方法。
实际上,我有以下内容:
@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响应?提前感谢。

请检查此示例,使用自定义反序列化程序 - Navneet Krishna
4个回答

43

我正在寻找一个简单的例子,以了解如何为Retrofit 2实现自定义转换器。不幸的是,我没有找到这样的例子。

我发现了这个例子,但至少对我来说,它对我的目的来说太复杂了。

幸运的是,我找到了解决方案。

这个解决方案是使用GSON反序列化器

我们不需要创建一个自定义转换器,我们只需要自定义GSON转换器

这里有一个很棒的教程。这是我用于解析我问题中描述的JSON的代码:

  • 登录反序列化器:定义如何将JSON解析为我们目标类的对象(使用条件和任何其他我们需要的内容)。

  • 自定义GSON转换器:构建一个使用我们自定义反序列化器的GSON转换器。


这将为相同类型的响应添加一个静态转换器工厂。如果我想使不同响应对象的解析变成可选的呢?我可能会有各种 API 的不同响应,其中包括可选和固定响应对象。 - Rushi M Thakker
一个简单的例子,你可以看一下Retrofit的标量转换器:https://github.com/square/retrofit/tree/master/retrofit-converters/scalars/src/main/java/retrofit2/converter/scalars - simne7
客户要求将存储库更新为私有。但我只是使用 GitHub Gist 更新了链接。 - JCarlosR

9
我发现@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()
}

2
编译这两个库以供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;
        }

    }

}

2
这里有一个例子。
简言之:
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();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接