微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

java – GSON忽略类型错误的元素

我正在使用Retrofit(与OkHttp和GSON组合)与在线网络服务进行通信.
webservice包含了所有响应的认包装,类似于:
{  
  "resultCode":"OK","resultObj":"Can be a string or JSON object / array","error":"","message":""
}

在此示例中,resultCode将为OK或NO.此外,当处理请求时发生错误时,错误和消息只有任何内容.最后,但并非最不重要的是,resultObj将包含调用的实际结果(该示例中是一个字符串,但有些调用返回一个JSON数组或一个JSON对象).

要处理这个元数据,我创建了一个泛型类,像这样:

public class ApiResult<T> {

    private String error;
    private String message;
    private String resultCode;
    private T resultObj;

    // + some getters,setters etcetera
}

我还创建了代表有时在resultObj中给出的响应的类,并且我已经定义了一个用于Retrofit的接口,看起来有点像这样:

public interface SomeWebService {

    @GET("/method/string")
    ApiResult<String> someCallThatReturnsAString();

    @GET("/method/pojo")
    ApiResult<SomeMappedResult> someCallThatReturnsAnObject();

}

只要请求有效,这一切都正常.但是当服务器端发生错误时,它仍然会返回一个String类型的resultObj.这会导致SomeCallThatReturnsAnObject在Retrofit RestAdapter / GSON库中崩溃,并显示如下消息:

retrofit.RetrofitError:
com.google.gson.JsonSyntaxException:
java.lang.IllegalStateException:

Expected BEGIN_OBJECT but was STRING at line 1 column 110 path $.resultObj

现在,最后我的问题是:

>有没有(容易的)告诉GSON,如果它不符合预期的类型,它应该忽略(也就是“取消”)一个属性
>我可以告诉GSON将空字符串视为null吗?

解决方法

像这样定义你的模型:
public class ApiResult {

    private String error;
    private String message;
    private String resultCode;
    private MyResultObject resultObj;
}

然后,为MyResultObject创建一个TypeAdapterFactory:

public class MyResultObjectAdapterFactory implements TypeAdapterFactory {

    @Override
    @SuppressWarnings("unchecked")
    public <T> TypeAdapter<T> create(Gson gson,Typetoken<T> type) {
        if (type.getRawType()!= MyResultObject.class) return null;

        TypeAdapter<MyResultObject> defaultAdapter = (TypeAdapter<MyResultObject>) gson.getDelegateAdapter(this,type);
        return (TypeAdapter<T>) new MyResultObjectAdapter(defaultAdapter);
    }

    public class MyResultObjectAdapter extends TypeAdapter<MyResultObject> {

        protected TypeAdapter<MyResultObject> defaultAdapter;


        public MyResultObjectAdapter(TypeAdapter<MyResultObject> defaultAdapter) {
            this.defaultAdapter = defaultAdapter;
        }

        @Override
        public void write(JsonWriter out,MyResultObject value) throws IOException {
            defaultAdapter.write(out,value);
        }

        @Override
        public MyResultObject read(JsonReader in) throws IOException {
            /* 
            This is the critical part. So if the value is a string,Skip it (no exception) and return null.
            */
            if (in.peek() == JsonToken.STRING) {
                in.skipValue();
                return null;
            }
            return defaultAdapter.read(in);
        }
    }
}

最后,为Gson注册MyResultObjectAdapterFactory:

Gson gson = new GsonBuilder()
    .registerTypeAdapterFactory(new MyResultObjectAdapterFactory())
    .create();

现在,当使用该Gson对象反序列化一个ApiResult json时,如果它是一个字符串,那么resultObj将被设置为null.

我希望这能解决你的问题=)

原文地址:https://www.jb51.cc/java/124026.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐