使用 JSend 格式通过 Retrofit 将 JSON 响应转换为 POJO?

Posted

技术标签:

【中文标题】使用 JSend 格式通过 Retrofit 将 JSON 响应转换为 POJO?【英文标题】:Converting JSON response to POJO with Retrofit using JSend format? 【发布时间】:2017-07-20 12:48:38 【问题描述】:

我必须使用使用 JSend 格式的 API。

长话短说,它使用的是 HTTP 状态代码,表示状态如下:

200 就是成功 406 未经授权

这很好,因为我可以从中确定我的 API 请求是否成功。

但是:

由于 JSend 格式有它自己的东西,它在响应时也有一个小的状态指示器,就像这样:


    status : "success",
    data :  "post" :  "id" : 2, "title" : "Another blog post", "body" : "More content" 

所以它有一个“状态”字段,它还显示 API 请求是否成功。

问题:

为了解析对 POJO 的响应而进行了改造,因此它假定响应仅包含模型并且没有成功的指示符,例如:(模型后实例)

 "id" : 2, "title" : "Another blog post", "body" : "More content" 

我的问题是:

有解决办法吗? 我可以预先解析状态指示符,拆分响应的“数据”(模型)部分,然后再对其进行改造以仅解析该部分吗?

如果不是,我将不得不为我的每个模型添加一个“状态”属性,这显然不是一种可步行的方式,我不会这样做。

我是否应该坚持手动解析并使用ResponseBody 而不是我的模型在

void onResponse(Call<T> call, Response<T> response);T 类型参数?

因为这样我可以使用.string() 并将字符串转换为 JSON,然后我可以手动解析我的模型,就像为它们编写解析器一样。

我真的很想使用 Retrofit 的功能进行自动解析,因为有了JSend,我无法想象如果无论如何要做到这一点。

我无法更改 API,它将成为这种方式。

【问题讨论】:

【参考方案1】:

你可以做的是你可以在不使用它的情况下获得发布请求的状态。 问题是参数名称不是字符串,在POJO中不会被解析。但是你可以像这样得到你请求的状态。

@Override
            public void onResponse(Call<Object> call, retrofit2.Response<Object> response) 
                alertDialog.dismiss();
                if (response.isSuccessful() && response.body() != null) 
                    //if the response is received here it means it was success
                else if(response.errorBody()!=null)
                    //if the response is received here it means it was error
                
            

            @Override
            public void onFailure(Call<Object> call, Throwable t) 
                //if the response is received here it means it was failure
                t.printStackTrace();
            
        );

编辑 通过这种方式,您可以获得使用 pojo 的状态,并且您可以像 link 中那样简单地解析错误

编辑 1 此外,为了获得正确的错误代码,您可以将回调类扩展为类似

public class ErrorValues 
    public int code=0;
    public String error;

然后如果请求完成有错误。里面

else if(response.errorBody()!=null)
 int error=response.body.code == 404 ....
                    

这样你可以检查请求抛出了哪个错误代码。

【讨论】:

【参考方案2】:

一种可能的方法是为您的模型创建一个包装器,例如

public class Example<T> 
    String status;
    T data;

    public String getStatus() 
        return status;
    

    public void setStatus(String status) 
        this.status = status;
    

    public T getData() 
        return data;
    

    public void setData(T data) 
        this.data = data;
    

【讨论】:

【参考方案3】:

这是我的Response 课程。

public class Response<T> implements Serializable 
private T data;
private String status;

public T getData() 
    return data;


public void setData(T data) 
    this.data = data;


public String getStatus() 
    return status;


public void setStatus(String status) 
    this.status = status;

这是我的 api 调用。

Callback<com.shippn.api.models.Response<T>> callback = new Callback<com.shippn.api.models.Response<T>>() 
        @Override
        public void onResponse(Call<com.shippn.api.models.Response<T>> call, Response<com.shippn.api.models.Response<T>> response) 
            checkStatus(response.body());
        

        @Override
        public void onFailure(Call<com.shippn.api.models.Response<T>> call, Throwable t) 
            fail();
        
    ;
    call.enqueue(callback);

T 参数是来自 api 的数据类型。我的意思是,如果你想在Post 中获取数据,请输入Post insted of T。如果你想得到ArrayList&lt;Post&gt;,请输入ArrayList&lt;Post&gt;

如果您的 api 响应中data 字段为空或 null,Response.data 将为 null 或空,它不会抛出异常。

当您收到 api 的响应时,首先检查 Response.status 是否“成功”。如果是“成功”,则从Response 获取数据,如果不是,则采取您的错误操作。

【讨论】:

优雅的解决方案。谢谢。 我很高兴听到这个消息,也感谢@AdamVarhegyi 的赏金

以上是关于使用 JSend 格式通过 Retrofit 将 JSON 响应转换为 POJO?的主要内容,如果未能解决你的问题,请参考以下文章

使用Retrofit2+RxJava2+ProtoBuf实现网络请求

如何使用Retrofit解决IllegalArgumentException“格式错误的内容类型:...”

使用 Retrofit 上传 JSON 格式的多部分图像数据?

当列表的各个项目使用Retrofit和Gson的格式不同时,如何解析json列表?

如何使用 Retrofit 将参数传递给 POST 请求,然后序列化请求?

Retrofit 官方文档