この質問は以前に尋ねられたかもしれませんが、それは決定的に答えられませんでした。 1つの改造全体のJSONをRetrofitリクエストの本文の中に正確にポストするのはどのくらいですか?
同様の質問を参照してください ここ 。それとも、この答えは正しいですか - URLエンコードされ、フィールドとして渡される必要があります ?私が接続しているサービスは、投稿の本文に未加工のJSONを期待しているだけなので、本当にそうしないことを願っています。 JSONデータの特定のフィールドを探すようには設定されていません。
これを restperts で一度だけ明確にしたいのです。 1人がRetrofitを使わないと答えました。もう1つはその構文について確信が持てませんでした。他の人はそうだと思いますが、それはURLエンコードされてフィールドに配置されている場合にのみ可能です(私の場合は受け入れられません)。いいえ、Androidクライアントのすべてのサービスを書き直すことはできません。そして確かに、主要なプロジェクトでは、JSONコンテンツをフィールドプロパティ値として渡すのではなく、生のJSONをポストするのが一般的です。正しく理解して先に進みましょう。これがどのように行われるかを示す文書や例を誰かが指すことができますか?または、それが実行できない、または実行できない理由を正当な理由で説明してください。
更新:私は100%の確実性で言うことができる一つのこと。あなたはGoogleのVolleyでこれをすることができます。それは正しく組み込まれています。レトロフィットでこれを行うことができますか?
@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つあります。
生バイトとJSON MIMEタイプを送信するには、 TypedByteArray を使用します。
String json = "{\"foo\":\"kit\",\"bar\":\"kat\"}";
TypedInput in = new TypedByteArray("application/json", json.getBytes("UTF-8"));
FooResponse response = foo.postRawJson(in);
サブクラス TypedStringTypedJsonString
クラスを作成します。
public class TypedJsonString extends TypedString {
public TypedJsonString(String body) {
super(body);
}
@Override public String mimeType() {
return "application/json";
}
}
そして#1と同じようにそのクラスのインスタンスを使います。
はい、私はそれが遅れていることを知っていますが、誰かがおそらくこれから利益を得るでしょう。
Retrofit2の使用:
私は昨晩この問題に出くわし、VolleyからRetrofit2に移行しました(そしてOP状態として、これはJsonObjectRequest
でVolleyに直接組み込まれました)、そしてJakeの答えはRetrofit1.9、Retrofit2にはTypedString
がありません。
私のケースでは、JSONObjectに変換されたいくつかのnull値を含むMap<String,Object>
を送信する必要がありました(@FieldMap
で飛行せず、特殊文字も変換されず、一部は変換されます)。そして Square :
@Bodyアノテーションを使用して、HTTPリクエスト本文として使用するオブジェクトを指定できます。
オブジェクトは、Retrofitインスタンスで指定されたコンバーターを使用して変換されます。コンバーターが追加されていない場合は、RequestBodyのみを使用できます。
したがって、これはRequestBody
およびResponseBody
を使用するオプションです。
インターフェースで@Body
とRequestBody
を使用します
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())
}
クラスの代わりに、ボディパラメータを送信するためにHashMap<String, Object>
を直接使用することもできます。
interface Foo {
@POST("/jayson")
FooResponse postJson(@Body HashMap<String, Object> body);
}
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", "[email protected]");
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) {
}
}
JsonObject
を使うのがその方法です:
このようにあなたのインターフェースを作成します。
public interface laInterfaz{
@POST("/bleh/blah/org")
void registerPayer(@Body JsonObject bean, Callback<JsonObject> callback);
}
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*/
サービスに連絡してください。
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());
}
};
そしてそれだ!私の個人的な意見では、それはpojosを作り、クラスの混乱を扱うことよりもずっと良いです。これはもっとずっときれいです。
私は特にJakeがTypedString
サブクラス above を提案しているのが好きです。実際にプッシュアップする予定の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)依存関係を追加する
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 Handlerクラスを作る
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クラスを作成する
覚えている
- ターゲット言語: Java ソースタイプ:JSON - 注釈スタイル:Gson - 選択 ゲッターとセッターを含む - また選択可能 追加のプロパティを許可
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")
フォームデータパラメータの他のチェック方法はこちら link
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();
}
}
これまでの努力の結果、基本的な違いはJsonObject
の代わりにJSONObject
をパラメータとして送信する必要があることです。
ScalarsConverterFactoryを後付けに追加します。
gradleで:
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を投稿することができます。
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
トップの答えに基づいて、私はすべての要求のために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
とマークされたリクエストは、その後Retrofitに渡すことができます。
@Body
パラメータとして複合オブジェクトを使用すると、RetrofitのGSONConverter
ではうまくいかないことがわかりました(それを使用しているという仮定の下で)。それを扱うときはJsonObject
ではなくJSONObject
を使用する必要があります。明確にすることなくNameValueParams
を追加します - ロギングインターセプターの依存性やその他の卑劣な行動を追加する場合にのみ確認できます。
だから私はこれに取り組むための最善のアプローチを見つけたRequestBody
を使用しています。あなたは単純なapi呼び出しであなたのオブジェクトをRequestBody
に変えてそれを起動します。私の場合は、地図を変換しています。
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>
追加のクラスを作成したくない場合や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)
ここで与えられた答えをより明確にするために、これが拡張機能の使用方法です。 これはKotlinを使用している場合のみです
com.squareup.okhttp3:okhttp:4.0.1
を使用している場合、MediaTypeおよびRequestBodyのオブジェクトを作成する古い方法は廃止されており、では使用できません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)
私がこれを試してみました:あなたがあなたのRetrofitインスタンスを作成しているとき、retrofitビルダーにこのコンバーターファクトリーを加えてください:
gsonBuilder = new GsonBuilder().serializeNulls()
your_retrofit_instance = Retrofit.Builder().addConverterFactory( GsonConverterFactory.create( gsonBuilder.create() ) )
API呼び出しごとにpojoクラスを作成したくない場合は、ハッシュマップを使用できます。
HashMap<String,String> hashMap=new HashMap<>();
hashMap.put("email","[email protected]");
hashMap.put("password","1234");
そして、このように送ってください
Call<JsonElement> register(@Body HashMap registerApiPayload);