Android Gson解析Jsonデータプロシージャと解析ルールのカスタマイズ方法(下)

5496 ワード

前の2篇の文章は主に問題の根源を探して解決の構想に着いて、解決方法は比較的に複雑で、ここは1種の最も簡単な解決方法を提供して、あまり多くのものを変える必要はありません:
たとえば、一般的なバックグラウンドで返されるデータフォーマットは次のとおりです.
ノーマルデータ
{"code":200,"data":{"id":"adsd","name":"Weipru"},"msg":"success","timeStamp":"20191015102953"}

dataが存在しないデータ
{"code":1000,"data":"","msg":"   !","timeStamp":"20191014094718"}

私たち自身のHttp応答エンティティに対応

public class HttpMessage {
    private int code;
    private T data;
    private String msg;
    private String timeStamp;

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public String getTimeStamp() {
        return timeStamp;
    }

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }

    public void setTimeStamp(String timeStamp) {
        this.timeStamp = timeStamp;
    }
    
}

通常のバックグラウンド・プロセスへのアクセス
  • バックグラウンドAPI
  • public interface GsonTestAPI {
        @GET("/user/list")
        Call>> getUserList();
    
        @GET("/user/info")
        Call> getUserInfo();
    }
  • APIを呼び出し、データ
  • を取得する
      messageCall.enqueue(new Callback>() {
                @Override
                public void onResponse(Call> call, Response> response) {
                    Log.i(TAG, "onResponse: " + response.body().getCode());
                }
    
                @Override
                public void onFailure(Call> call, Throwable t) {
                    Log.i(TAG, "onResponse: " + t.getMessage());
                    t.printStackTrace();
                }
            });

    同様に、dataタイプが汎用配列の場合:
      Call>> messageCall = userServiceAPI.getUserList();
            messageCall.enqueue(new Callback>>() {
                @Override
                public void onResponse(Call>> call, Response>> response) {
                    Log.i(TAG, "onResponse: " + response.body().getCode());
                }
    
                @Override
                public void onFailure(Call>> call, Throwable t) {
                    Log.i(TAG, "onResponse: " + t.getMessage());
                    t.printStackTrace();
                }
            });

    正常なデータを返すと、正しく解析して返すことができますが、直接異常を投げ出しているかどうかは、どのように解決しますか?
    同様に、独自のコンバータをカスタマイズする必要があります.3つのクラスが必要です.
  • GsonConverFactory
  • GsonResponseBodyConverter  
  • GsonRequestBodyConverter

  • ソースコードから直接コピーして自分の名前に変えればいいのですが、現在は応答体変換器GsonResponseBodyConverterのみが処理されています.コードは以下の通りです.
  • GsonConverFactoryで独自のコンバータを返し、ディスプレイキー
  • に戻る
    
        @Override
        public Converter responseBodyConverter(Type type, Annotation[] annotations,
                                                                Retrofit retrofit) {
            Log.w("TYPE", "    " + type.getTypeName());//
            TypeAdapter> adapter = gson.getAdapter(TypeToken.get(type));
            return new WGsonResponseBodyConverter<>(gson, adapter);
        }
    
        @Override
        public Converter, RequestBody> requestBodyConverter(Type type,
                                                              Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
            TypeAdapter> adapter = gson.getAdapter(TypeToken.get(type));
            return new WGsonRequestBodyConverter<>(gson, adapter);
        }
  • WGsonResponseBodyConverterにて状態判断:
  •  public T convert(ResponseBody value) throws IOException {
            try {
                //  value       ,              ,     
                String reponseString = value.string();
                HttpMessage httpMessage = gson.fromJson(reponseString, HttpMessage.class);
                if (httpMessage.getCode() != 200) {
                    return (T) httpMessage;//    ,data        
                }
    
                MediaType contentType = value.contentType();
                Charset charset = contentType != null ? contentType.charset(UTF_8) : UTF_8;
                InputStream inputStream = new ByteArrayInputStream(reponseString.getBytes());
                Reader reader = new InputStreamReader(inputStream, charset);
                JsonReader jsonReader = gson.newJsonReader(reader);
    
                return adapter.read(jsonReader);
            } finally {
                value.close();
            }
        }

    カスタム変換器を使用します.
     userServiceAPI = new Retrofit.Builder()
                    .client(builder.build())
                    .baseUrl(this.host).addConverterFactory(WGsonConverFactory.create())//        
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .build()
                    .create(GsonTestAPI.class);

    問題を簡単かつ完璧に解決する