如何使用 Retrofit 和 RxJa 处理两个 JSON 响应?

How to handle two JSON response with Retrofit and RxJa?

我正在向服务器发送 API 请求,我可以获得两个 JSON 响应:

经过身份验证的用户响应:

{"status":"ok","tekst":"8bc6c9cf-293f-11e5-9940-448a5b5dd2bd","requestID":9034}

未经身份验证的用户响应:

{"authenticationError":"User authentication failed"}

改装服务:

public interface LiveService {
    @GET("live.php")
    Observable<Response<LiveResponse>> getLive();
}

这是对服务器的 Retrofit 请求:

retrofit.create(LiveService.class)
            .getLive()
            .subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Subscriber<Response<LiveResponse>>() {
                @Override
                public void onCompleted() {

                }

                @Override
                public void onError(Throwable e) {
                    liveView.onLiveError(e);
                }

                @Override
                public void onNext(Response<LiveResponse> response) {


                }
            });

我如何处理 onNext 中的响应以检查我是否收到针对经过身份验证的用户或未经身份验证的用户的 JSON 响应?

您的模型需要将两者的所有字段合并到一个 POJO 中。就这么简单:-)

不存在的经过身份验证的用户/未经身份验证的用户的那些将只是空的。

更清楚...

让我们看两个不同的回复。这是我遇到的两个随机 JSON 有效负载。

   {
        "title": "Sample Konfabulator Widget",
        "name": "main_window",
        "width": 500,
        "height": 500
    }



   { 
        "src": "Images/Sun.png",
        "name": "sun1",
        "hOffset": 250,
        "vOffset": 250,
        "alignment": "center"
    }

将我们引向一个组合对象,例如

    {
    "title": "Sample Konfabulator Widget",
    "name": "main_window",
    "width": 500,
    "height": 500,
    "src": "ImagesSun.png",
    "hOffset": 250,
    "vOffset": 250,
    "alignment": "center"
   }

给我们一个看起来像这样的 POJO。

public class MyPojo
{
    private String alignment;

    private String title;

    private String hOffset;

    private String height;

    private String width;

    private String name;

    private String src;

    private String vOffset;

    public String getAlignment ()
    {
        return alignment;
    }

    public void setAlignment (String alignment)
    {
        this.alignment = alignment;
    }

    public String getTitle ()
    {
        return title;
    }

    public void setTitle (String title)
    {
        this.title = title;
    }

    public String getHOffset ()
    {
        return hOffset;
    }

    public void setHOffset (String hOffset)
    {
        this.hOffset = hOffset;
    }

    public String getHeight ()
    {
        return height;
    }

    public void setHeight (String height)
    {
        this.height = height;
    }

    public String getWidth ()
    {
        return width;
    }

    public void setWidth (String width)
    {
        this.width = width;
    }

    public String getName ()
    {
        return name;
    }

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

    public String getSrc ()
    {
        return src;
    }

    public void setSrc (String src)
    {
        this.src = src;
    }

    public String getVOffset ()
    {
        return vOffset;
    }

    public void setVOffset (String vOffset)
    {
        this.vOffset = vOffset;
    }

    @Override
    public String toString()
    {
        return "ClassPojo [alignment = "+alignment+", title = "+title+", hOffset = "+hOffset+", height = "+height+", width = "+width+", name = "+name+", src = "+src+", vOffset = "+vOffset+"]";
    }
}

改造只能处理一种数据类型。也许您可以使用 authenticated_user & unauthenticated_user 对象创建主用户对象。也许你应该要求后端团队 return 一个布尔值或任何变量来识别数据的类型。

class User {
AuthUser authUser;
UnAuthUser unAuthUSer;
}

我同意 StarWind,添加另一个字段将帮助您稍后决定如何处理响应,但首先您需要调整最终结果不是 Response<T> 而是正文(对象)的方法.这可以通过 RxJava 通过以下方式链接调用轻松完成:接收响应,检查是否成功,检查反序列化的正文对象是否包含身份验证错误字段。

retrofit.create(LiveService.class).getLive().flatMap(new Function<Response<LiveResponse>, ObservableSource<LiveResponse>>() {
            @Override
            public ObservableSource<LiveResponse> apply(Response<LiveResponse> liveResponse) throws Exception {
                LiveResponse body =  liveResponse.body();
                if(liveResponse.isSuccessful() && body != null && body.getAuthenticationError() == null){ //probably check http error code too
                    return Observable.just(body);
                }else if(body != null){
                    throw new AuthenticationException(body.getAuthenticationError());
                }else{
                 throw IllegalArgumentException("something terribly happened here"); }
            }
        }).subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Observer<LiveResponse>() {
                @Override
                public void onComplete() {

                }

                @Override
                public void onError(Throwable e) {
                    liveView.onLiveError(e); //authentication error maybe or network excp
                }

                @Override
                public void onNext(LiveResponse body) {


                }
            });

请注意,我使用了 RxJava 2,但您可以轻松地在 RxJava 1 中重写它。