改造リクエストの本文に未加工のJSON全体をPOSTする方法は?


284

この質問は以前に尋ねられた可能性がありますが、明確に回答されていませんでした。Retrofitリクエストの本文内に未加工のJSON全体をどのように正確にポストしますか?

ここで同様の質問を参照してください。または、この回答は、URLエンコードされてフィールドとして渡される必要があること正しいですか?私が接続しているサービスは投稿の本文にそのままのJSONを期待しているだけなので、私は本当に望みません。JSONデータの特定のフィールドを検索するように設定されていません。

私はちょうどでこれを明確にしたいrestpertsきっぱりと。一人はレトロフィットを使用しないと答えました。もう1つは構文が明確ではありませんでした。別の人はそれが可能であると考えていますが、そのフォームがURLエンコードされてフィールドに配置されている場合のみです(私の場合は受け入れられません)。いいえ、Androidクライアントのすべてのサービスを再コーディングすることはできません。そしてはい、JSONコンテンツをフィールドプロパティ値として渡すのではなく、未加工のJSONをポストすることは、主要なプロジェクトでは非常に一般的です。それを正しく理解して次に進みましょう。これがどのように行われるかを示すドキュメントまたは例を誰かが指すことができますか?または、それができる/すべきではない正当な理由を提供してください。

更新:100%確実に言えることの1つ。Googleのボレーでこれを行うことができます。内蔵されています。これをレトロフィットで実行できますか?


7
ジェイク・ウォートンの投稿は正しいです!回答としてマークしてください!
edotassi 2014

1
あなたはjsonObjectをよりよく使うかもしれません。
superUser 2015

完璧に動作しますRequestBody> -このようなRequestBody body = RequestBody.create(MediaType.parse("text/plain"), text);詳細な回答のためfuturestud.io/tutorials/...
Kidus Tekeste

回答:


461

@Body注釈は、単一の要求の本体を画定します。

interface Foo {
  @POST("/jayson")
  FooResponse postJson(@Body FooRequest body);
}

RetrofitはデフォルトでGsonを使用するため、FooRequestインスタンスはリクエストの唯一の本体としてJSONとしてシリアル化されます。

public class FooRequest {
  final String foo;
  final String bar;

  FooRequest(String foo, String bar) {
    this.foo = foo;
    this.bar = bar;
  }
}

で呼び出す:

FooResponse = foo.postJson(new FooRequest("kit", "kat"));

次の本体が生成されます:

{"foo":"kit","bar":"kat"}

Gsonドキュメントは、オブジェクトのシリアル化がどのように機能するかについて多くを持っています。

ここで、本当に自分で「生の」JSONを本文として送信したい場合(ただし、Gsonを使用してください!)、引き続き以下を使用できますTypedInput

interface Foo {
  @POST("/jayson")
  FooResponse postRawJson(@Body TypedInput body);
}

TypedInputは、「MIMEタイプが関連付けられたバイナリデータ」として定義されます。上記の宣言で生データを簡単に送信するには2つの方法があります。

  1. TypedByteArrayを使用して、未加工のバイトとJSON MIMEタイプを送信します。

    String json = "{\"foo\":\"kit\",\"bar\":\"kat\"}";
    TypedInput in = new TypedByteArray("application/json", json.getBytes("UTF-8"));
    FooResponse response = foo.postRawJson(in);
    
  2. TypedStringをサブクラスしてTypedJsonStringクラスを作成します。

    public class TypedJsonString extends TypedString {
      public TypedJsonString(String body) {
        super(body);
      }
    
      @Override public String mimeType() {
        return "application/json";
      }
    }
    

    次に、そのクラスのインスタンスを#1と同様に使用します。


5
しかし、ポージョを作らずにこれを作る方法はありますか?
スーパーユーザー2015

28
これはレトロフィット2では機能しません。TypedInputおよびTypedStringクラスは削除されました。
Ahmed Hegazy 2015年

2
@jakewharton TypedStringそれが削除された後、私たちは何ができるのですか?
Jared Burrows 2016年

12
Retrofit2の場合、を使用RequestBodyして生のボディを作成できます。
bnorm

4
この例外が発生しますjava.lang.IllegalArgumentException: Unable to create @Body converter for class MatchAPIRequestBody (parameter #1)
Shajeel Afzal 2017

154

クラスの代わりに、を直接使用しHashMap<String, Object>てボディパラメータを送信することもできます。

interface Foo {
  @POST("/jayson")
  FooResponse postJson(@Body HashMap<String, Object> body);
}

2
そのとき、HashMap <String、Object>のようなハッシュマップを作成できます。複雑な配列やオブジェクトのJSONを作成することは可能です。
学習者2015

2
これは、ある種のPOJOに縛られたくない場合に最適です。
Tim

2
@Nilレトロフィットを使用してjsonオブジェクトを送信することはできません...あなたはpojoまたは私の答えに固執します...これはレトロフィットの性質です。この質問についてもっと知りたい場合は、彼はレトロフィット開発者であるJake Whartonであり、彼の答えはpojoでも利用できます。
学習者は、

5
私が手IllegalArgumentException: Unable to create @Body converter for java.util.HashMap<java.lang.String, java.lang.Object>モシで。これを機能させるにはGsonが必要だと思います
osrl 2017年

2
Kotlinを使用している場合は、<String、Any>のハッシュマップを使用します
peresisUser

148

はい、私はそれが遅いことを知っていますが、誰かがおそらくこれから利益を得るでしょう。

Retrofit2の使用:

私は昨夜、この問題をVolleyからRetrofit2に移行しました(OP状態では、これはを使用してVolleyに直接組み込まれましたJsonObjectRequest。Jakeの答えはRetrofit1.9の正しいものですが、Retrofit2にはありませんTypedString

私の場合は、送信側の必要はありませんMap<String,Object>(と飛ばないだろうというJSONObjectに変換し、いくつかのヌル値を含むことができることを@FieldMap、どちらも特殊な文字は、いくつかのGETは変換さん)、次の@bnormsがヒントので、とで述べたようにスクエア

@Bodyアノテーションを使用して、オブジェクトをHTTPリクエスト本文として使用するように指定できます。

オブジェクトは、Retrofitインスタンスで指定されたコンバーターを使用して変換されます。コンバーターが追加されていない場合は、RequestBodyのみを使用できます。

したがって、これはRequestBodyand を使用したオプションResponseBodyです。

あなたのインターフェース@BodyRequestBody

public interface ServiceApi
{
    @POST("prefix/user/{login}")
    Call<ResponseBody> login(@Path("login") String postfix, @Body RequestBody params);  
}

呼び出しポイントでを作成しRequestBody、それをMediaTypeとして記述し、JSONObjectを使用してマップを適切な形式に変換します。

Map<String, Object> jsonParams = new ArrayMap<>();
//put something inside the map, could be null
jsonParams.put("code", some_code);

RequestBody body = RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"),(new JSONObject(jsonParams)).toString());
//serviceCaller is the interface initialized with retrofit.create...
Call<ResponseBody> response = serviceCaller.login("loginpostfix", body);

response.enqueue(new Callback<ResponseBody>()
    {
        @Override
        public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> rawResponse)
        {
            try
            {
             //get your response....
              Log.d(TAG, "RetroFit2.0 :RetroGetLogin: " + rawResponse.body().string());
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }

        @Override
        public void onFailure(Call<ResponseBody> call, Throwable throwable)
        {
        // other stuff...
        }
    });

これが誰にも役立つことを願っています!


上記のエレガントなKotlinバージョン。アプリケーションコードの残りの部分でJSON変換からパラメーターを抽象化できます。

interface ServiceApi {

    fun login(username: String, password: String) =
            jsonLogin(createJsonRequestBody(
                "username" to username, "password" to password))

    @POST("/api/login")
    fun jsonLogin(@Body params: RequestBody): Deferred<LoginResult>

    private fun createJsonRequestBody(vararg params: Pair<String, String>) =
            RequestBody.create(
                okhttp3.MediaType.parse("application/json; charset=utf-8"), 
                JSONObject(mapOf(*params)).toString())

}

2
ええ、私はこのためにたくさんの複雑な応答を見ています。Retrofit2を使用していて、ボレーを実行したい場合JsonObjectRequestは、これだけです。いい答えだ。
VicVu 2016年

2
Retrofitは、「nameValuePairs」という名前のキーをすべてのjsonオブジェクトの最上部に追加します。どうすればこれを削除できますか@TommySM
nr5

1
ありがとうございました!これは私の問題を解決しました。これで、POJOを作成せずにJSONObjectを直接送信できます。
Erfan GLMPR 2017年

1
これは、post a null value他の方法では無視されていたrequestBodyのプロパティに私を助ける唯一のソリューションです。
Shubhral

私は遅れていることを知っていますjsonParams.put("code", some_code);が、3行目には何がありますか?
Naveen Niraula

81

Retrofit2あなたが使用する必要があり、生であなたのパラメータを送信したい、スカラーを

まずこれをあなたのgradleに追加してください:

compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
compile 'com.squareup.retrofit2:converter-scalars:2.3.0'

あなたのインターフェース

public interface ApiInterface {

    String URL_BASE = "http://10.157.102.22/rest/";

    @Headers("Content-Type: application/json")
    @POST("login")
    Call<User> getUser(@Body String body);

}

アクティビティ

   public class SampleActivity extends AppCompatActivity implements Callback<User> {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sample);

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(ApiInterface.URL_BASE)
                .addConverterFactory(ScalarsConverterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        ApiInterface apiInterface = retrofit.create(ApiInterface.class);


        // prepare call in Retrofit 2.0
        try {
            JSONObject paramObject = new JSONObject();
            paramObject.put("email", "sample@gmail.com");
            paramObject.put("pass", "4384984938943");

            Call<User> userCall = apiInterface.getUser(paramObject.toString());
            userCall.enqueue(this);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }


    @Override
    public void onResponse(Call<User> call, Response<User> response) {
    }

    @Override
    public void onFailure(Call<User> call, Throwable t) {
    }
}

9
ここでのトリックは、Gsonの前のスカラーアダプターです。それ以外の場合、Gsonは手動でシリアル化されたJSONを文字列にラップします。
TWiStErRob 2017

2
jonathan-nolasco-barrientos .baseUrl(ApiInterface.ENDPOINT)を.baseUrl(ApiInterface.URL_BASE)に変更する必要があります
Milad Ahmadi

2
を使用するGsonConverterFactory場合、.toString()は必要ありません。の代わりにCall<User> getUser(@Body JsonObject body);使用して宣言し、直接渡すことができます。それはうまくいきます。JsonObjectJSONObjectparamObject
Igor de Lorenzi

優れたシンプルなアプローチ。その日を救った
イタイ・スペクター

1
@IgordeLorenziが問題を解決します。これは、スプリングブートを使用してjsonを取得しているため、gsonからJsonObjectのみが正常に機能するためです
haidarvm '28

44

使用JsonObject方法は次のとおりです。

  1. 次のようなインターフェースを作成します。

    public interface laInterfaz{ 
        @POST("/bleh/blah/org")
        void registerPayer(@Body JsonObject bean, Callback<JsonObject> callback);
    }
  2. JsonObjectをjsons構造に従って作成します。

    JsonObject obj = new JsonObject();
    JsonObject payerReg = new JsonObject();
    payerReg.addProperty("crc","aas22");
    payerReg.addProperty("payerDevManufacturer","Samsung");
    obj.add("payerReg",payerReg);
    /*json/*
        {"payerReg":{"crc":"aas22","payerDevManufacturer":"Samsung"}}
    /*json*/
  3. サービスを呼び出す:

    service.registerPayer(obj, callBackRegistraPagador);
    
    Callback<JsonObject> callBackRegistraPagador = new Callback<JsonObject>(){
        public void success(JsonObject object, Response response){
            System.out.println(object.toString());
        }
    
        public void failure(RetrofitError retrofitError){
            System.out.println(retrofitError.toString());
        }
    };

そして、その!私の個人的な意見では、それはポージョを作ったり、クラスの混乱を扱うよりもはるかに優れています。これははるかにきれいです。


1
jsonobjectクラスでspecif値を送信したくない場合はどうすればよいですか?上記の検証可能などの注釈を使用できますか?
AliGürelli、2016年

1
上記の例を見るとわかるように、オブジェクトであるJsonObjectは注釈を使用しません。あなたの場合、特定の値を送信したくない場合は、プロパティとして追加しないだけかもしれません...
superUser

1
つまり、クラスで宣言されている値を送信したくないのです。ところで問題を修正しました。名前が公開されているアノテーションがありました。
AliGürelli、2016年

2
これが最も柔軟な方法です。フィールドの数がわからない場合や、フィールド名が+1であることがわからない場合でも、jsonオブジェクトを作成できます
Stoycho Andreev '30

1
エラーを取得しているサービスメソッドはvoidを返すことができません。メソッドAPIServices.signUpUser用
Erum

11

上記TypedStringサブクラスに関するジェイクの提案が特に気に入っています。実際、プッシュアップする予定のPOSTデータの種類に基づいて、さまざまなサブクラスを作成できます。各サブクラスには、独自の一貫した微調整のカスタムセットがあります。

Retrofit APIのJSON POSTメソッドにヘッダーアノテーションを追加するオプションもあります…

@Headers( "Content-Type: application/json" )
@POST("/json/foo/bar/")
Response fubar( @Body TypedString sJsonBody ) ;

…しかし、サブクラスを使用することは、より明確に自己文書化します。

@POST("/json/foo/bar")
Response fubar( @Body TypedJsonString jsonBody ) ;

1
JWの提案からTypedJsonStringを使用した明確な例でその日を救った
ミロスラヴィン

10

1)依存関係を追加します

 compile 'com.google.code.gson:gson:2.6.2'
compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'

2)APIハンドラクラスを作成する

    public class ApiHandler {


  public static final String BASE_URL = "URL";  

    private static Webservices apiService;

    public static Webservices getApiService() {

        if (apiService == null) {

           Gson gson = new GsonBuilder()
                    .setLenient()
                    .create();
            Retrofit retrofit = new Retrofit.Builder().addConverterFactory(GsonConverterFactory.create(gson)).baseUrl(BASE_URL).build();

            apiService = retrofit.create(Webservices.class);
            return apiService;
        } else {
            return apiService;
        }
    }


}

3)Jsonスキーマ2 pojoからBeanクラスを作成する

覚えておいてください
-Target言語:Javaの -Sourceタイプ:JSON -annotationスタイル:Gsonは-Select ゲッターとセッターを含め 、あなたが選択することができ-also 追加のプロパティを許可します

http://www.jsonschema2pojo.org/

4)API呼び出しからインターフェースを作成する

    public interface Webservices {

@POST("ApiUrlpath")
    Call<ResponseBean> ApiName(@Body JsonObject jsonBody);

}

あなたがフォームデータパラメータを持っているなら、以下の行を追加してください

@Headers("Content-Type: application/x-www-form-urlencoded")

form-dataパラメータの他の方法はこのリンクをチェックしてください

5)パラメータとして本体に渡すためのJsonObjectを作成する

 private JsonObject ApiJsonMap() {

    JsonObject gsonObject = new JsonObject();
    try {
        JSONObject jsonObj_ = new JSONObject();
        jsonObj_.put("key", "value");
        jsonObj_.put("key", "value");
        jsonObj_.put("key", "value");


        JsonParser jsonParser = new JsonParser();
        gsonObject = (JsonObject) jsonParser.parse(jsonObj_.toString());

        //print parameter
        Log.e("MY gson.JSON:  ", "AS PARAMETER  " + gsonObject);

    } catch (JSONException e) {
        e.printStackTrace();
    }

    return gsonObject;
}

6)このようにApiを呼び出す

private void ApiCallMethod() {
    try {
        if (CommonUtils.isConnectingToInternet(MyActivity.this)) {
            final ProgressDialog dialog;
            dialog = new ProgressDialog(MyActivity.this);
            dialog.setMessage("Loading...");
            dialog.setCanceledOnTouchOutside(false);
            dialog.show();

            Call<ResponseBean> registerCall = ApiHandler.getApiService().ApiName(ApiJsonMap());
            registerCall.enqueue(new retrofit2.Callback<ResponseBean>() {
                @Override
                public void onResponse(Call<ResponseBean> registerCall, retrofit2.Response<ResponseBean> response) {

                    try {
                        //print respone
                        Log.e(" Full json gson => ", new Gson().toJson(response));
                        JSONObject jsonObj = new JSONObject(new Gson().toJson(response).toString());
                        Log.e(" responce => ", jsonObj.getJSONObject("body").toString());

                        if (response.isSuccessful()) {

                            dialog.dismiss();
                            int success = response.body().getSuccess();
                            if (success == 1) {



                            } else if (success == 0) {



                            }  
                        } else {
                            dialog.dismiss();


                        }


                    } catch (Exception e) {
                        e.printStackTrace();
                        try {
                            Log.e("Tag", "error=" + e.toString());

                            dialog.dismiss();
                        } catch (Resources.NotFoundException e1) {
                            e1.printStackTrace();
                        }

                    }
                }

                @Override
                public void onFailure(Call<ResponseBean> call, Throwable t) {
                    try {
                        Log.e("Tag", "error" + t.toString());

                        dialog.dismiss();
                    } catch (Resources.NotFoundException e) {
                        e.printStackTrace();
                    }
                }

            });

        } else {
            Log.e("Tag", "error= Alert no internet");


        }
    } catch (Resources.NotFoundException e) {
        e.printStackTrace();
    }
}

9

複合オブジェクトを@Bodyパラメーターとして使用すると、レトロフィットではうまく機能しないことがわかりましたGSONConverter(使用しているという前提の下で)。あなたはそれを使用するときに使用する必要がJsonObjectありJSONObject、それをNameValueParams冗長にすることなく追加します-ロギングインターセプターの別の依存関係および他の悪意を追加した場合にのみ確認できます。

したがって、これに取り組むための最善のアプローチはを使用することRequestBodyです。RequestBody単純なapi呼び出しでオブジェクトをにして起動します。私の場合、マップを変換しています:

   val map = HashMap<String, Any>()
        map["orderType"] = orderType
        map["optionType"] = optionType
        map["baseAmount"] = baseAmount.toString()
        map["openSpotRate"] = openSpotRate.toString()
        map["premiumAmount"] = premiumAmount.toString()
        map["premiumAmountAbc"] = premiumAmountAbc.toString()
        map["conversionSpotRate"] = (premiumAmountAbc / premiumAmount).toString()
        return RequestBody.create(MediaType.parse("application/json; charset=utf-8"), JSONObject(map).toString())

そしてこれは呼び出しです:

 @POST("openUsvDeal")
fun openUsvDeal(
        @Body params: RequestBody,
        @Query("timestamp") timeStamp: Long,
        @Query("appid") appid: String = Constants.APP_ID,
): Call<JsonObject>

2
まあ、これは一晩グーグルした後に私を助けました。
W4R10CK

8

ScalarsConverterFactoryをレトロフィットに追加します。

グラドルで:

implementation'com.squareup.retrofit2:converter-scalars:2.5.0'

あなたの改造:

retrofit = new Retrofit.Builder()
            .baseUrl(WEB_DOMAIN_MAIN)
            .addConverterFactory(ScalarsConverterFactory.create())
            .addConverterFactory(GsonConverterFactory.create(gson))
            .build();

呼び出しインターフェースの@BodyパラメータをStringに変更します。追加することを忘れないでください@Headers("Content-Type: application/json")

@Headers("Content-Type: application/json")
@POST("/api/getUsers")
Call<List<Users>> getUsers(@Body String rawJsonString);

今、あなたは生のjsonを投稿することができます。


6

API呼び出しごとにpojoクラスを作成したくない場合は、ハッシュマップを使用できます。

HashMap<String,String> hashMap=new HashMap<>();
        hashMap.put("email","this@gmail.com");
        hashMap.put("password","1234");

そして、このように送信します

Call<JsonElement> register(@Body HashMap registerApiPayload);

4

多くの努力の結果、基本的な違いは、JsonObjectではなくJSONObjectパラメータとしてを送信する必要があることです。


私も同じ間違いをしていました:p
Mehtab Ahmed

4

以下を使用してjsonを送信します

final JSONObject jsonBody = new JSONObject();
    try {

        jsonBody.put("key", "value");

    } catch (JSONException e){
        e.printStackTrace();
    }
    RequestBody body = RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"),(jsonBody).toString());

そしてそれをURLに渡します

@Body RequestBody key

4

上位の回答に基づいて、すべてのリクエストに対してPOJOを作成する必要がないという解決策があります。

例、私はこのJSONを投稿したいと思います。

{
    "data" : {
        "mobile" : "qwer",
        "password" : "qwer"
    },
    "commom" : {}
}

次に、次のような共通のクラスを作成します。

import java.util.Map;
import java.util.HashMap;

public class WRequest {

    Map<String, Object> data;
    Map<String, Object> common;

    public WRequest() {
        data = new HashMap<>();
        common = new HashMap<>();
    }
}

最後に、jsonが必要なとき

WRequest request = new WRequest();
request.data.put("type", type);
request.data.put("page", page);

アノテーション@Bodyが付けられたリクエストは、レトロフィットに渡されます。


4

追加のクラスを作成したくない場合や使用したくない場合は、を使用JSONObjectできますHashMap

後付けインターフェース:

@POST("/rest/registration/register")
fun signUp(@Body params: HashMap<String, String>): Call<ResponseBody>

コール:

val map = hashMapOf(
    "username" to username,
    "password" to password,
    "firstName" to firstName,
    "surname" to lastName
)

retrofit.create(TheApi::class.java)
     .signUp(map)
     .enqueue(callback)

3

Retrofitでraw jsonを送信するために必要なもの。

1)必ず次のヘッダーを追加し、他の重複するヘッダーを削除してください。それ以来、Retrofit の公式ドキュメントで、彼らは具体的に言及しています-

ヘッダーは互いに上書きしないことに注意してください。同じ名前のすべてのヘッダーがリクエストに含まれます。

@Headers({"Content-Type: application/json"})

2) a。コンバーターファクトリを使用している場合は、jsonを文字列、JSONObject、JsonObject、さらにはPOJOとして渡すことができます。また、チェックは済んでいるScalarConverterFactoryだけGsonConverterFactoryで仕事はしません。

@POST("/urlPath")
@FormUrlEncoded
Call<Response> myApi(@Header("Authorization") String auth, @Header("KEY") String key, 
                     @Body JsonObject/POJO/String requestBody);

2)b。コンバーターファクトリを使用していない場合は、Retrofitのドキュメントに記載されているように、okhttp3のRequestBodyを使用する必要があります。

オブジェクトは、Retrofitインスタンスで指定されたコンバーターを使用して変換されます。コンバーターが追加されていない場合は、RequestBodyのみを使用できます。

RequestBody requestBody=RequestBody.create(MediaType.parse("application/json; charset=utf-8"),jsonString);

@POST("/urlPath")
@FormUrlEncoded
Call<Response> myApi(@Header("Authorization") String auth, @Header("KEY") String key, 
                 @Body RequestBody requestBody);

3)成功!!


2

これが、現在のバージョンretrofit 2.6.2で機能します。

まず、Scalars ConverterをGradle依存関係のリストに追加する必要があります。これにより、java.lang.Stringオブジェクトがtext / plainリクエスト本文に変換されます。

implementation'com.squareup.retrofit2:converter-scalars:2.6.2'

次に、コンバーターファクトリをRetrofitビルダーに渡す必要があります。後でサービスに渡された@Bodyパラメータを変換する方法をRetrofitに伝えます。

private val retrofitBuilder: Retrofit.Builder by lazy {
    Retrofit.Builder()
        .baseUrl(BASE_URL)
        .addConverterFactory(ScalarsConverterFactory.create())
        .addConverterFactory(GsonConverterFactory.create())
}

注:私の改造ビルダーには2つのコンバーターがGsonあり、 Scalars両方を使用できますが、Jsonボディを送信するには、フォーカスを削除するScalars必要がない場合に焦点を合わせる必要がありますGson

次に、文字列本体パラメーターを使用してサービスを改良します。

@Headers("Content-Type: application/json")
@POST("users")
fun saveUser(@Body   user: String): Response<MyResponse>

次に、JSON本文を作成します

val user = JsonObject()
 user.addProperty("id", 001)
 user.addProperty("name", "Name")

サービスに電話する

RetrofitService.myApi.saveUser(user.toString())

2

✅✅✅✅✅✅✅✅✅✅✅✅実用的な ソリューション ✅✅✅✅✅✅✅✅✅✅✅✅

作成中 OkHttpClientには、レトロフィットに使用されます。

このようなインターセプターを追加します。

 private val httpClient = OkHttpClient.Builder()
        .addInterceptor (other interceptors)
        ........................................

        //This Interceptor is the main logging Interceptor
        .addInterceptor { chain ->
            val request = chain.request()
            val jsonObj = JSONObject(Gson().toJson(request))

            val requestBody = (jsonObj
            ?.getJSONObject("tags")
            ?.getJSONObject("class retrofit2.Invocation")
            ?.getJSONArray("arguments")?.get(0) ?: "").toString()
            val url = jsonObj?.getJSONObject("url")?.getString("url") ?: ""

            Timber.d("gsonrequest request url: $url")
            Timber.d("gsonrequest body :$requestBody")

            chain.proceed(request)
        }

        ..............
        // Add other configurations
        .build()

これで、すべてのレトロフィットコールのURLとリクエストの本文がログインLogcatます。フィルターする"gsonrequest"


1

私はこれを試しました:レトロフィットインスタンスを作成しているときに、このコンバーターファクトリーをレトロフィットビルダーに追加します。

gsonBuilder = new GsonBuilder().serializeNulls()     
your_retrofit_instance = Retrofit.Builder().addConverterFactory( GsonConverterFactory.create( gsonBuilder.create() ) )

1

TommySMの回答に基づいて問題を解決しました(前を参照)。しかし、ログインする必要はありませんでした。次のように、Retrofit2を使用してhttps GraphQL APIをテストしました。

  1. jsonアノテーションを使用して、BaseResponseクラスを定義しました(jackson.annotation.JsonPropertyをインポート)。

    public class MyRequest {
        @JsonProperty("query")
        private String query;
    
        @JsonProperty("operationName")
        private String operationName;
    
        @JsonProperty("variables")
        private String variables;
    
        public void setQuery(String query) {
            this.query = query;
        }
    
        public void setOperationName(String operationName) {
            this.operationName = operationName;
        }
    
        public void setVariables(String variables) {
            this.variables = variables;
        }
    }
  2. インターフェースで呼び出し手順を定義しました:

    @POST("/api/apiname")
    Call<BaseResponse> apicall(@Body RequestBody params);
  3. テスト本体でapicallと呼ばれる:MyRequestタイプの変数を作成します(たとえば、「myLittleRequest」)。

    Map<String, Object> jsonParams = convertObjectToMap(myLittleRequest);
    RequestBody body = 
         RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"),
                        (new JSONObject(jsonParams)).toString());
    response = hereIsYourInterfaceName().apicall(body).execute();

0

ここで与えられた答えをより明確にするために、これは拡張関数の使用方法です。これは、Kotlinを使用している場合のみです

MediaTypeおよびRequestBodyのcom.squareup.okhttp3:okhttp:4.0.1オブジェクトを作成するための古いメソッドを使用している場合は廃止されており、Kotlinでは使用できません。

拡張関数を使用して文字列からMediaTypeオブジェクトとResponseBodyオブジェクトを取得する場合は、まず、次の行をそれらを使用する予定のクラスに追加します。

import okhttp3.MediaType.Companion.toMediaType
import okhttp3.RequestBody.Companion.toRequestBody

この方法でMediaTypeのオブジェクトを直接取得できるようになりました

val mediaType = "application/json; charset=utf-8".toMediaType()

RequestBodyのオブジェクトを取得するには、最初に、送信するJSONObjectをこの方法で文字列に変換します。mediaTypeオブジェクトをそれに渡す必要があります。

val requestBody = myJSONObject.toString().toRequestBody(mediaType)

0

私がコードの下に書いたデータを送受信するためのボレーと改造の速度を比較したかった(改造部分用)

最初の依存関係:

dependencies {
     implementation 'com.squareup.retrofit2:retrofit:2.4.0'
     implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
}

次にインターフェース:

 public interface IHttpRequest {

    String BaseUrl="https://example.com/api/";

    @POST("NewContract")
    Call<JsonElement> register(@Body HashMap registerApiPayload);
}

データをサーバーに送信するためのパラメーターを設定する関数(MainActivity):

private void Retrofit(){

    Retrofit retrofitRequest = new Retrofit.Builder()
            .baseUrl(IHttpRequest.BaseUrl)
            .addConverterFactory(GsonConverterFactory.create())
            .build();

    // set data to send
    HashMap<String,String> SendData =new HashMap<>();
    SendData.put("token","XYXIUNJHJHJHGJHGJHGRTYTRY");
    SendData.put("contract_type","0");
    SendData.put("StopLess","37000");
    SendData.put("StopProfit","48000");

    final IHttpRequest request=retrofitRequest.create(IHttpRequest.class);

    request.register(SendData).enqueue(new Callback<JsonElement>() {
        @Override
        public void onResponse(Call<JsonElement> call, Response<JsonElement> response) {
            if (response.isSuccessful()){
                Toast.makeText(getApplicationContext(),response.body().toString(),Toast.LENGTH_LONG).show();
            }
        }

        @Override
        public void onFailure(Call<JsonElement> call, Throwable t) {

        }
    });

}

そして、私の場合、ボレーよりもレトロフィットの方が速いことがわかりました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.