如何为可以是字符串或自定义对象的对象创建JSON转换器

时间:2018-07-10 09:53:26

标签: android json kotlin gson retrofit2

我们的后端实现了Login 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 2,Gson和RxJava2CallAdapterFactory。

3 个答案:

答案 0 :(得分:1)

通过这种方式制作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;
}

}

ResponseData ..

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

        }
    });

答案 1 :(得分: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;
    }

和带有RxJava2的Retrofit2

MaybeObserver<ResponseData> getUserData(...)

但是,我认为您的API设计会带来一些潜在的故障。请改用HTTP响应代码。

答案 2 :(得分:0)

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