Retrofitは、リクエストパラメータの文字列が空のフィールドを削除します

Retrofitは、リクエストパラメータの文字列が空のフィールドを削除します

要求する

会社の開発では、このような要件が発生
しました。バックグラウンドに送信されるすべてのネットワークリクエストで、bodyパラメータのフィールドの値が空の文字列の場合、このフィールドは削除され、バックグラウンドに送信されません。
たとえば、本文を介して送信するデータが次の長さであるとします。

{
    
    
	"param1":"1",
	"param2":"2",
	"param3":"3",
	"param4":"",
	"param5":null,
}

実際に送信されたパラメーター:
変更前:

{
    
    
	"param1":"1",
	"param2":"2",
	"param3":"3",
	"param4":""
}

変更後:

{
    
    
	"param1":"1",
	"param2":"2",
	"param3":"3"
}

例からわかるように、実装する関数は、Retrofitがリクエストを送信するときに、値が本文の空の文字列であるパラメータを削除することです。
ConverterFactoryをGsonとして指定した後、Retrofitはnull削除するパラメーターのデフォルト値を削除しますが、パラメーター値は空の文字列であるため、独自に処理する必要があります。パラメーター値を削除すると、空の文字列になります。

デフォルトのGsonConverterFactoryコードとしてConverterFactoryを指定します。

 Retrofit retrofit = new Retrofit.Builder()
           .baseUrl("https://wwww.baidu.com")
           .addConverterFactory(GsonConverterFactory.create())
           .build();

成し遂げる

解決策は実際には難しくありません。Retrofitのコンバーターメカニズムを使用することです。
GsonConverterは私たちのプロジェクトで使用されています:

    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'

言い換えると、オブジェクトのシリアル化と逆シリアル化はGsonオブジェクトを使用します。したがって、次のステップは当然、GsonConverterを構成してこの要件を達成する方法を考えることです。
実際、この要件は実装が非常に簡単で、コードは次のとおりです。

		TypeAdapter<String> stringTypeAdapter = new TypeAdapter<String>() {
    
    
            @Override
            public String read(JsonReader in) throws IOException {
    
    
                JsonToken peek = in.peek();
                if (peek == JsonToken.NULL) {
    
    
                    in.nextNull();
                    return null;
                }
                /* coerce booleans to strings for backwards compatibility */
                if (peek == JsonToken.BOOLEAN) {
    
    
                    return Boolean.toString(in.nextBoolean());
                }
                return in.nextString();
            }
            @Override
            public void write(JsonWriter out, String value) throws IOException {
    
    
            	// 下面这个if是关键代码,指定序列化时,遇到空串则直接输出null值。
            	// 由于Gson默认是不序列化null的,所以这里就相当于在序列化时排除了空串的字段
                if ("".equals(value)) {
    
    
                    out.nullValue();
                    return;
                }
                out.value(value);
            }
        };

        Gson gson = new GsonBuilder().registerTypeAdapter(String.class, stringTypeAdapter).create();
        Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("https://wwww.baidu.com")
            .addConverterFactory(GsonConverterFactory.create(gson))
            .build();

キーコードは、コードのコメントに記載されているとおりです。
ここでの考え方は指定されたシリアル化および逆シリアル化ルール変数タイプに対してのみを指定するGsonことTypeAdapterですString
このStringタイプTypeAdapterの記述に関しては、実際Gsonオブジェクトのソースコードを参照します。

考え

この要件に最初に遭遇したとき、私はおそらく方向性を知っていましたが、具体的な詳細を達成する方法を知りませんでした。シリアル化と逆シリアル化を実現するためにRetrofit、自分で定義できることだけを知っていますConverterしかし、String逆シリアル化しない型の空の文字列を実装する方法がわかりません。
私の考えは
次のとおりです。まず、GsonConverterFactory.create()メソッドにパラメーターを持つメソッドがありますGsonConverterFactory.create(Gson gson)。次に、要件を実現Factoryするgsonオブジェクトを構成することで、この要件達成できます。
次にGsonこのnullタイプのオブジェクトはデフォルトではシリアル化さませんこれはどのように達成されますか?これを理解すれば、同じ方法でGson空の文字列逆シリアル化できると思います。
それから、上記の考えに基づいて、私Gsonはソースコードを見始めました私は次の段落を見ました:

public static final TypeAdapterFactory STRING_FACTORY = newFactory(String.class, STRING);

1つはここTypeAdapterFactory定義されており、これは明らかにStringを処理するために使用されます。後でnewFactoryメソッドに渡されるSTRINGオブジェクトの定義次のとおりです。

public static final TypeAdapter<String> STRING = new TypeAdapter<String>() {
    
    
    @Override
    public String read(JsonReader in) throws IOException {
    
    
      JsonToken peek = in.peek();
      if (peek == JsonToken.NULL) {
    
    
        in.nextNull();
        return null;
      }
      /* coerce booleans to strings for backwards compatibility */
      if (peek == JsonToken.BOOLEAN) {
    
    
        return Boolean.toString(in.nextBoolean());
      }
      return in.nextString();
    }
    @Override
    public void write(JsonWriter out, String value) throws IOException {
    
    
      out.value(value);
    }
  };

ここを参照してください。最後に、ここで行う必要があるのは、writecontentメソッドを再定義することです。
Gsonはデフォルトnullではシリアル化されていないため、文字列が空のときにnullを出力するように指定できますこのようにして、デフォルトで、空の文字列を出力しないという目標を達成できます。

スペースに限りがありますので、実際に読んで確認した内容は上記の内容をはるかに上回っていますが、上記の内容がポイントであり、他の内容も自分の工夫で扱えると思います。Gsonのソースコード自体は難しくないからです。

おすすめ

転載: blog.csdn.net/awy1988/article/details/114107308