Retrofit使用チュートリアル:RetrofitでGSONは同じフィールドの異なるタイプのjsonデータを解析します
5514 ワード
前言
本文は主にプロジェクトでjsonを処理する実際の応用である.
ダイレクトコード
データを解析するときに、同じフィールドと異なるデータ型の問題が発生する可能性があります.次のデータを例に挙げます.
返されたデータからretDataのタイプが2種類(オブジェクトと配列)になっていることがわかり、オブジェクトが返されて失敗したときにGSONが解析できず異常を放出するように定義されている場合.ここでGSONはRetrofitを組み合わせて使用しているので、解析に失敗した場合、異常はSubscriberの次の方法にコールバックされます.
このonError法では,他の有用なデータを得ることはできない.例えば、エラーメッセージを取得してユーザーに提示したいのですが、ここでは仕方がありません.この問題を解決する方法は2つある: 逆シーケンス化解析データ を用いる.データを異常放出し、処理 を行う.の逆シーケンス化にはいくつかの限界があり、ここでretMsgは未知の汎用型を定義してもよく解決できない.だから以下の方法で異常データを放出します.
一、Retrofitを初期化する際にカスタムブロッキングを使用する.
二、カスタムresponseBodyが返したデータを解析する.
三、code値に基づいて異なるクラス解析データを選択する.
convertメソッドでは,返すデータを具体的な汎用解析するように指定しない.code値で今回のリクエストを判定:成功したらtypeタイプの解析データを返し,失敗したら我々があらかじめ定義したHttpErrResultオブジェクトを用いて解析し,ResultExceptionでエラー情報を返す.
四、カスタムRetrofitのSubscriberメソッドの解析失敗と成功情報.
我々の以前の異常はonErrorメソッドにコールバックし,ResultException異常であるか否かを判断することにより,異常情報を取り出してPresenter処理にコールバックする.
githubソースダウンロード
本文は主にプロジェクトでjsonを処理する実際の応用である.
ダイレクトコード
データを解析するときに、同じフィールドと異なるデータ型の問題が発生する可能性があります.次のデータを例に挙げます.
//
{
"retMsg": "success",
"retData": {
"city": " ",
"phone": "13282191888",
"prefix": "1328219",
"province": " ",
"supplier": " "
},
"errNum": 0
}
//
{
"errNum": -1,
"retMsg": "[132821918888]\u6b64\u53f7\u7801\u4e0d\u662f\u5408\u6cd5\u7684\u624b\u673a\u53f7!",
"retData": []
}
返されたデータからretDataのタイプが2種類(オブジェクトと配列)になっていることがわかり、オブジェクトが返されて失敗したときにGSONが解析できず異常を放出するように定義されている場合.ここでGSONはRetrofitを組み合わせて使用しているので、解析に失敗した場合、異常はSubscriberの次の方法にコールバックされます.
public void onError(Throwable e) {}
このonError法では,他の有用なデータを得ることはできない.例えば、エラーメッセージを取得してユーザーに提示したいのですが、ここでは仕方がありません.
一、Retrofitを初期化する際にカスタムブロッキングを使用する.
Retrofit mAdapter = new Retrofit.Builder()
.baseUrl(SERVER)
//
.addConverterFactory(GsonDConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.client(getBuilder().build())
.build();
二、カスタムresponseBodyが返したデータを解析する.
public final class GsonDConverterFactory extends Converter.Factory {
public static GsonDConverterFactory create() {
return create(new Gson());
}
public static GsonDConverterFactory create(Gson gson) {
return new GsonDConverterFactory(gson);
}
private final Gson gson;
private GsonDConverterFactory(Gson gson) {
if (gson == null) throw new NullPointerException("gson == null");
this.gson = gson;
}
@Override public Converter < ResponseBody,
?>responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
return new GsonResponseBodyConverter < >(gson, type);
}
@Override public Converter < ?,
RequestBody > requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
TypeAdapter < ?>adapter = gson.getAdapter(TypeToken.get(type));
return new GsonRequestBodyConverter < >(gson, adapter);
}
}
三、code値に基づいて異なるクラス解析データを選択する.
convertメソッドでは,返すデータを具体的な汎用解析するように指定しない.code値で今回のリクエストを判定:成功したらtypeタイプの解析データを返し,失敗したら我々があらかじめ定義したHttpErrResultオブジェクトを用いて解析し,ResultExceptionでエラー情報を返す.
final class GsonResponseBodyConverter < T > implements Converter < ResponseBody,
T > {
private final Gson gson;
private final Type type;
GsonResponseBodyConverter(Gson gson, Type type) {
this.gson = gson;
this.type = type;
}
/**
* 、
*/
@Override public T convert(ResponseBody value) throws IOException {
String response = value.string();
try {
// type HttpResult PhoneBean retData 。
HttpResult result = gson.fromJson(response, HttpResult.class);
int code = result.getErrNum();
if (code == 0) {
return gson.fromJson(response, type);
} else {
Log.d("HttpManager", " err==:" + response);
HttpErrResult errResponse = gson.fromJson(response, HttpErrResult.class);
if (code == -1) {
throw new ResultException(errResponse.getRetMsg(), code);
} else {
throw new ResultException(errResponse.getErrMsg(), code);
}
}
} finally {
value.close();
}
}
}
四、カスタムRetrofitのSubscriberメソッドの解析失敗と成功情報.
我々の以前の異常はonErrorメソッドにコールバックし,ResultException異常であるか否かを判断することにより,異常情報を取り出してPresenter処理にコールバックする.
public abstract class HttpResultCallBack < M > extends Subscriber < HttpResult < M >> {
/**
*
*/
public abstract void onResponse(M m, int status);
public abstract void onErr(String msg, int status);
/**
*
*/
@Override public void onCompleted() {}
@Override public void onError(Throwable e) {
if (e != null) {
if (e instanceof ResultException) {
ResultException err = (ResultException) e;
onErr(err.getErrMsg(), GlobalVar.RESULT_UNLOGIN);
} else {
onErr(" , ", GlobalVar.RESULT_UNLOGIN);
Log.d("HttpManager", " ==:" + e.getMessage());
}
}
onCompleted();
}
/**
* Http
*/
private void onHttpFail(String msg, int status) {
onErr(msg, status);
}
@Override public void onNext(HttpResult < M > result) {
String jsonResponse = new Gson().toJson(result);
Log.d("HttpManager", " ok==:" + jsonResponse);
if (result.getErrNum() == GlobalVar.RESULT_OK) {
onResponse(result.getRetData(), GlobalVar.RESULT_OK);
} else {
onHttpFail(result.getErrMsg(), GlobalVar.RESULT_UNLOGIN);
}
}
}
githubソースダウンロード