【问题标题】:How to create a JSON Converter for objects that can be either a String or a Custom Object如何为可以是字符串或自定义对象的对象创建 JSON 转换器
【发布时间】:2018-07-10 09:53:25
【问题描述】:

我们的后端实现了一个登录 API,响应如下:

成功响应:

{
    "response": "SUCCESS",
    "details": {
        "user_id": "912341",
        "name": "John Doe",
        "email": "johndoe@gmail.com",
        "address": "John Doe's House",
        "birthdate": "2018-07-09",
        "profile_file_id": null
    }
}

错误响应:

{
    "response": "FAILED",
    "details": "Invalid email"
}

如何使我的 GSON 和 Retrofit Serializer 动态化以允许这样的数据更改?我正在使用 Retrofit 2、Gson 和 RxJava2CallAdapterFactory。

【问题讨论】:

  • 在 GSON 的帮助下可能无法实现,要么您必须添加不同的密钥字符串,例如 "error":"error message" 并检查它是 null 还是空?
  • 你想同时获取数据。

标签: android json kotlin gson retrofit2


【解决方案1】:
public class ResponseData {

    @SerializedName("response")
    private String response;

    @SerializedName("details")
    private String details;

    public String getError(){
        if(response.equals("FAILED")
            return details;
        else return null; 
    }

    public UserData getUserData(){
        if(response.equals("SUCCESS")
           return new Gson().fromJson(details, UserData.class);
        else return null;
    }

Retrofit2 和 RxJava2

MaybeObserver<ResponseData> getUserData(...)

但是,在我看来,您的 API 设计会带来一些失败的可能性。请改用 HTTP 响应代码。

【讨论】:

  • 这是真的。我建议下次将其更改为更语义化的方式。但是,我将您的 String details 更改为 JsonElement。但这有效!谢谢!
【解决方案2】:

像这样制作 pojo 类..

public class Details{

@SerializedName("address")
private String address;

@SerializedName("birthdate")
private String birthdate;

@SerializedName("profile_file_id")
private Object profileFileId;

@SerializedName("user_id")
private String userId;

@SerializedName("name")
private String name;

@SerializedName("email")
private String email;

public void setAddress(String address){
    this.address = address;
}

public String getAddress(){
    return address;
}

public void setBirthdate(String birthdate){
    this.birthdate = birthdate;
}

public String getBirthdate(){
    return birthdate;
}

public void setProfileFileId(Object profileFileId){
    this.profileFileId = profileFileId;
}

public Object getProfileFileId(){
    return profileFileId;
}

public void setUserId(String userId){
    this.userId = userId;
}

public String getUserId(){
    return userId;
}

public void setName(String name){
    this.name = name;
}

public String getName(){
    return name;
}

public void setEmail(String email){
    this.email = email;
}

public String getEmail(){
    return email;
}

}

响应数据..

public class ResponseData extends ErrorResponse{

@SerializedName("response")
private String response;

@SerializedName("details")
private String details;

public void setResponse(String response){
    this.response = response;
}

public String getResponse(){
    return response;
}

public void setDetails(String details){
    this.details = details;
}

public String getDetails(){
    return details;
}

}

错误响应..

public class ErrorResponse {

@SerializedName("response")
private String response;

@SerializedName("details")
private String details;

}

让 api 调用接口..

@GET("path")
Call<ResponseData> getUserData();

API 调用。

        Call<ResponseData> dataCall=apiInterface.getUserData();
    dataCall.enqueue(new Callback<ResponseData>() {
        @Override
        public void onResponse(Call<ResponseData> call, Response<ResponseData> response) {
            if (response!=null && response.isSuccessful() && response.body()!=null){

            }
            else{
                if (response.errorBody()!=null){
                    ErrorResponse errorResponse=new Gson().fromJson(response.errorBody().toString(),ErrorResponse.class);
                    Log.d("Error data",response.errorBody().toString());
                }
            }
        }

        @Override
        public void onFailure(Call<ResponseData> call, Throwable t) {

        }
    });

【讨论】:

    【解决方案3】:

    使用相同的属性来包含 2 种语义不同类型的信息是不正确的。您有点在内部对类应用多态性(使用某些内部属性的状态来决定其他某些属性的内容 type)。我要做的是添加另一个属性parallel do details,如errorDetails,在发生错误的情况下将填充错误原因。在这种情况下,您有 2 个单独的字段来根据响应类型处理数据。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-26
      • 1970-01-01
      • 1970-01-01
      • 2011-01-15
      相关资源
      最近更新 更多