SimpleXML和Retrofit:仅具有根元素的响应模型

时间:2015-12-10 11:08:04

标签: android xml retrofit simple-framework

我们正在开发一个带有XML API的Android项目,使用RxJavaRetrofitSimpleXML来处理请求和响应。响应的根源可以在两种类型之间变化:

<?xml version="1.0" encoding="UTF-8"?> 
<response>
 <Element1>Integer</Element1>
 <Element2>Integer</Element2>
 ...
</response>

<?xml version="1.0" encoding="UTF-8"?>
<error>
 <Element1>String</Element1>
 <Element2>Integer</Element2>
</error>

因此,我们使用XMLPullParse来解析不同模型的不同类型的响应及其附带的元素,这很好。

MyResponse :超类,它结合了可能的errorsvalid响应:

public abstract class MyResponse<T> {
    public final MyError error;
    public final T data;

    protected MyResponse(MyError mError, T data) {
        this.error = mError;
        this.data = data;
    }

    public final boolean isError() {
        return error != null;
    }

    @Override
    public String toString() {
        return "MyResponse{" +
                "error=" + error +
                ", data=" + data +
                '}';
    }

    public T getData() {
        return data;
    }
}

SessionTokenResponse :扩展MyResponse的response类示例

public class SessionTokenResponse extends MyResponse<SessionTokenResponseData>{
    public SessionTokenResponse(MyError mError, SessionTokenResponseData response) {
        super(mError, response);
}
}

SessionTokenResponseData :显示我们如何构建模型的示例类

@Root(name = "data")
public class SessionTokenResponseData {

    @Element(name = "Session")
    private String sessionInfo;

    @Element(name = "Token")
    private String tokenInfo;

    public String getSessionInfo() {
        return sessionInfo;
    }
    ....
}

RestClient - foo():我们的RestClient类中的一种方法,用于解析不同类型的响应。如果成功,则响应将<response>作为根元素,否则根元素将为<error>

类型
private final <T extends MyResponse, I> Func1<ResponseBody, Observable<T>> foo(final Class<T> cls, final Class<I> innerCls) {
    return new Func1<ResponseBody, Observable<T>>() {
        @Override
        public Observable<T> call(ResponseBody responseBody) {
            try {

                final String xmlString = responseBody.string();

                final XmlPullParser parser = Xml.newPullParser();
                parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
                parser.setInput(new ByteArrayInputStream(xmlString.getBytes(Charset.forName("UTF-8"))), null);
                parser.nextTag();

                final String rootTag = parser.getName();

                final Serializer serializer = new Persister();

                if (TextUtils.equals(rootTag, "error")) {
                    final MyError myError = serializer.read(MyError.class, xmlString);
                    return Observable.just((T) cls.getConstructor(MyError.class, innerCls).newInstance(myError, null));
                } else if (TextUtils.equals(rootTag, "response")) {
                    final I data = serializer.read(innerCls, xmlString);
                    return Observable.just((T) cls.getConstructor(HuiError.class, innerCls).newInstance(null, data));
                }

但我们遇到一种类型的响应问题,如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<response>
 OK
</response>

我们的问题是:如果没有元素,我们如何为这种响应构建模型?我们仍然需要能够区分具有<response>根的其他响应。

1 个答案:

答案 0 :(得分:1)

在一个自发的想法之后,我们自己找到了答案。 响应将扩展超类,并且不会包含任何其他模型类,例如我的示例类 SessionTokenResponseData ,但只包含字符串:

public class LoginResponse extends MyResponse<String>{
    public LoginResponse(MyError mError, String response) {
        super(mError, response);
    }
}

所以我们不需要在RestClient类方法中修改我们的手动解析,它工作正常。