Bir Retrofit talebinin gövdesinde tüm JSON'u hamle nasıl POST yapabilirim?


284

Bu soru daha önce sorulmuş olabilir ama hayır kesin olarak cevaplanmamıştı. Bir Retrofit talebi gövdesinde bir post ham JSON tam olarak nasıl?

Benzer soruyu burada görebilirsiniz . Yoksa bu cevap form url'si olarak kodlanmış ve alan olarak iletilmiş olması gerektiği doğru mu? Gerçekten ummuyorum, bağlandığım hizmetler sadece gönderinin gövdesinde ham JSON bekliyor. JSON verileri için belirli bir alanı arayacak şekilde ayarlanmamıştır.

Bunu sadece bir kez ve herkes için açıklayıcılarla açıklığa kavuşturmak istiyorum . Bir kişi Retrofit kullanmamaya cevap verdi. Diğeri sözdiziminden emin değildi. Bir diğeri evet yapılabilir ancak sadece form url kodlu ve bir alana yerleştirilirse (benim durumumda kabul edilemez) yapılabilir. Hayır, Android istemcim için tüm hizmetleri yeniden kodlayamıyorum. Ve evet, büyük projelerde, JSON içeriğini alan özelliği değerleri olarak aktarmak yerine ham JSON göndermek çok yaygındır. Hadi doğru yapalım ve devam edelim. Birisi bunun nasıl yapıldığını gösteren belgelere veya örneğe işaret edebilir mi? Ya da bunun yapılamaması / yapılmaması için geçerli bir neden belirtin.

GÜNCELLEME:% 100 kesin olarak söyleyebileceğim bir şey. Bunu Google'ın Voleybolu'nda yapabilirsiniz. Tam inşa edilmiş. Bunu Retrofit'te yapabilir miyiz?


7
Jake Wharton'un gönderisi doğru! Cevap olarak işaretle!
edotassi

1
JsonObject öğesini daha iyi kullanabilirsiniz.
superUser

ile mükemmel çalışıyor RequestBodyböyle -> RequestBody body = RequestBody.create(MediaType.parse("text/plain"), text);detaylı cevap için futurestud.io/tutorials/...
Kidus Tekeste

Yanıtlar:


461

@BodyAçıklama tek bir istek beden tanımlar.

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

Retrofit varsayılan olarak Gson kullandığından, FooRequestörnekler isteğin tek gövdesi olarak JSON olarak serileştirilir.

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

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

Şununla aranıyor:

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

Aşağıdaki vücudu verecektir:

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

GSON dokümanlar çok daha nesne seri hale nasıl çalıştığı hakkında sahiptir.

Eğer gerçekten vücuda kendin olarak "ham" JSON göndermek istediğiniz (! Ama bunun için GSON kullanın) Şimdi, eğer hala kullanarak yapabilirsiniz TypedInput:

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

TypedInput "İlişkili bir mime türüyle ikili veriler" olarak tanımlanır. Yukarıdaki beyan ile ham verileri kolayca göndermenin iki yolu vardır:

  1. Ham bayt ve JSON mime türünü göndermek için TypedByteArray öğesini kullanın :

    String json = "{\"foo\":\"kit\",\"bar\":\"kat\"}";
    TypedInput in = new TypedByteArray("application/json", json.getBytes("UTF-8"));
    FooResponse response = foo.postRawJson(in);
  2. Bir sınıf oluşturmak için TycString alt TypedJsonStringsınıfı:

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

    Ve sonra o sınıfın # 1 örneğine benzer bir örneği kullanın.


5
Bununla birlikte, çok iyi, bunu pojos yapmadan yapmak için yine de var mı?
superUser

28
Bu güçlendirme 2 üzerinde çalışmaz. TypedInput ve TypedString sınıfları kaldırıldı.
Ahmed Hegazy

2
@jakewharton TypedStringKaldırıldığından beri ne yapabiliriz ?
Jared Burrows

12
Retrofit2 RequestBodyiçin ham bir gövde oluşturmak için kullanabilirsiniz .
bnorm

4
Bu istisnayı alıyorumjava.lang.IllegalArgumentException: Unable to create @Body converter for class MatchAPIRequestBody (parameter #1)
Shajeel Afzal

155

Sınıflar yerine doğrudan HashMap<String, Object>vücut parametrelerini göndermek için

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

2
O zaman HashMap <String, Object> gibi Hash haritası oluşturabilirsiniz, biraz karmaşık diziler ve JSON nesneleri oluşturmak mümkün olabilir.
öğrenci

2
Bir çeşit POJO'ya bağlı olmak istemiyorsanız, bu mükemmeldir.
Tim

2
@Geliştirmeyi kullanarak json nesnesini gönderemezsiniz ... pojo ya da cevabımla uyuyorsunuz ... bu retrofitin doğası. .
Öğrenci

5
Ben olsun IllegalArgumentException: Unable to create @Body converter for java.util.HashMap<java.lang.String, java.lang.Object>Moshi ile. Sanırım bu iş için Gson gerekli
osrl

2
Kotlin kullanıyorsanız <String, Any> bir hashmap kullanın
peresisUser

148

Evet geç olduğunu biliyorum, ama birisi muhtemelen bundan fayda sağlayacaktır.

Retrofit2'yi kullanma:

Dün gece Volley'den Retrofit2'ye (ve OP'nin belirttiği gibi, bu Volley ile inşa edildi JsonObjectRequest) bu sorunla karşılaştım ve Jake'in cevabı Retrofit1.9 için doğru olmasına rağmen , Retrofit2'de yok TypedString.

Benim durumum Map<String,Object>, bir JSONObject'e dönüştürülen (neyle uçmayacak @FieldMap, ne de özel karakterleri de içermeyecek, bazıları dönüştürülmeyecek) bazı null değerler içerebilecek ve bu nedenle @bnorms ipucunu takip eden ve Square tarafından belirtildiği bir gönderilmesi gerekiyordu :

Bir nesne, @Body ek açıklamasıyla HTTP istek gövdesi olarak kullanılmak üzere belirtilebilir.

Nesne ayrıca Retrofit örneğinde belirtilen bir dönüştürücü kullanılarak dönüştürülecektir. Hiçbir dönüştürücü eklenmezse, yalnızca RequestBody kullanılabilir.

Bu kullanarak bir seçenektir Yani RequestBodyve ResponseBody:

Arayüz kullanımda @BodyolanRequestBody

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

Çağrı noktanızda RequestBodyMediaType olduğunu belirterek ve Haritanızı uygun biçime dönüştürmek için JSONObject kullanarak:

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...
        }
    });

Umarım bu herkese yardımcı olur!


Uygulama kodunuzun geri kalanındaki JSON dönüştürmesinden parametrelerin soyutlanmasına izin vermek için yukarıdakilerin zarif bir Kotlin sürümü:

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
Evet, bunun için birçok karmaşık yanıt görüyorum. Retrofit2 kullanıyorsanız ve volley yapmak istiyorsanız JsonObjectRequest, yapmanız gereken tek şey budur. İyi cevap.
VicVu

2
Retrofit, tüm json nesnelerinin üstüne "nameValuePairs" adlı bir anahtar ekler. Bunu @TommySM'den nasıl kaldırabilirim
nr5

1
Teşekkür ederim! Bu benim sorunumu çözdü. Şimdi JSONObject'i POJO oluşturmadan doğrudan gönderebilirim.
Erfan GLMPR

1
Bu, post a null valuerequestBody'deki bir mülk için bana yardımcı olan tek çözümdür, aksi takdirde göz ardı ediliyordu.
Shubhral

Geç kaldığımı biliyorum ama jsonParams.put("code", some_code);üçüncü sırada ne var ?
Naveen Niraula

81

In Retrofit2 Eğer kullanmalıdır ham içinde parametrelerini göndermek istediğiniz, skalar .

önce bunu grubunuza ekleyin:

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'

Arayüzünüz

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);

}

Aktivite

   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) {
    }
}

10
Buradaki hile, Gson'dan önce Skaler adaptördür, aksi takdirde Gson, manuel olarak serileştirilmiş JSON'unuzu bir String'e sarar.
TWiStErRob

2
Jonathan-nolasco-barrientos Eğer .baseUrl için .baseUrl (ApiInterface.ENDPOINT) (ApiInterface.URL_BASE) değiştirmek zorunda
Milad Ahmadi

2
Kullandığınızda GsonConverterFactory, .toString()gerekli değildir. Bunun yerine Call<User> getUser(@Body JsonObject body);kullanarak ilan edebilir ve doğrudan geçebilirsiniz . Sadece iyi çalışır. JsonObjectJSONObjectparamObject
Igor de Lorenzi

1
@IgordeLorenzi sorunumu çözmek, çünkü ben sadece json json almak için bahar çizme kullanıyorum gson gelen iyi çalışıyor
haidarvm

1
@IgordeLorenzi Skalerlerle kullanmak için daha iyi JSONObject veya JsonObject olan bir fark var mı?
Sumit Shukla

44

Kullanmak JsonObjectşu şekildedir:

  1. Arayüzünüzü şu şekilde oluşturun:

    public interface laInterfaz{ 
        @POST("/bleh/blah/org")
        void registerPayer(@Body JsonObject bean, Callback<JsonObject> callback);
    }
  2. JsonObject'i jsons yapısına göre yapın.

    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. Servisi arayın:

    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());
        }
    };

Ve bu onun! Kişisel görüşüme göre, bu pojos yapmak ve sınıf karışıklık ile çalışmak daha iyidir. Bu çok daha temiz.


1
Jsonobject sınıfında belirli bir değer göndermek istemezsem ne olur? bunun için geçerli olan hangi ek açıklamayı kullanabilirim?
Ali Gürelli

1
Yukarıdaki örneği görebileceğiniz gibi ... JsonObject bir nesne olduğu için herhangi bir açıklama kullanmaz. Sizin durumunuzda belirli bir değer göndermek istemiyorsanız, onu bir mülk olarak eklemeyebilirsiniz ...
superUser

1
Yani sınıfta beyan edilen değer göndermek istemiyorum. Btw sorunu çözdüm. Bu adın açıklandığı bir ek açıklama vardı.
Ali Gürelli

2
Bu en esnek yoldur. Kaç alanınız olacağını
bilmeseniz

1
im alma hatası Hizmet yöntemleri geçersiz döndüremez. yöntem APIServices.signUpUser için
Erum

11

Özellikle Jake'in yukarıdakiTypedString alt sınıf önerisini seviyorum . Gerçekten, her biri kendi özel tutarlı tweaks setine sahip olmayı planladığınız POST verisine dayanarak çeşitli alt sınıflar oluşturabilirsiniz.

Ayrıca, Retrofit API'nizdeki JSON POST yöntemlerinize başlık ek açıklama ekleme seçeneğiniz de var ...

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

… Ancak bir alt sınıf kullanmak daha açık bir şekilde kendi kendini belgelemektedir.

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

1
JW önerisinden TypedJsonString kullanarak günü net bir örnekle kurtardı
miroslavign

10

1) Bağımlılıklar ekleyin-

 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 sınıfı yapmak

    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 şema 2 pojo gelen fasulye sınıfları yapmak

Unutmayın
-Hedef dili: Java -Kaynak türü: JSON -Bir açıklama stili: Gson -select Alıcıları ve ayarlayıcıları dahil et - ayrıca Ek özelliklere izin ver'i de seçebilirsiniz

http://www.jsonschema2pojo.org/

4) api çağrı için arayüz yapmak

    public interface Webservices {

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

}

form-veri parametreleriniz varsa aşağıdaki satırı ekleyin

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

Form-veri parametresi için başka bir yol bu bağlantıyı kontrol et

5) parametre olarak vücuda geçmek için JsonObject yapmak

 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) Call Api bunu beğendi

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

@BodyParam olarak bileşik bir nesne kullandığınızda , Retrofit'in GSONConverter(bunu kullandığınız varsayımı altında) ile iyi çalışamayacağını buldum . Kullanmanız gerekir JsonObjectve bununla JSONObjectçalışırken değil , bu konuda NameValueParamsayrıntılı olmadan ekler - yalnızca günlük yakalayıcıya ve diğer maskaralıklara başka bir bağımlılık eklerseniz görebilirsiniz.

Yani bununla başa çıkmak için en iyi yaklaşımı buldum RequestBody. Nesnenizi RequestBodybasit bir API çağrısı ile çevirin ve başlatın. Benim durumumda bir haritayı dönüştürüyorum:

   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())

ve bu çağrı:

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

2
Bu gece boyunca çalıştıktan sonra bana yardımcı oldu.
W4R10CK

8

Güçlendirmeye ScalarsConverterFactory ekleyin:

sınıfta:

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

güçlendirme:

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

call interface @Body parametrenizi String olarak değiştirin, eklemeyi unutmayın @Headers("Content-Type: application/json"):

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

şimdi ham json gönderebilirsiniz.


6

Her API çağrısı için pojo sınıfı oluşturmak istemiyorsanız hashmap'yi kullanabilirsiniz.

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

Ve sonra böyle gönder

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

5

json göndermek için aşağıdakini kullan

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());

ve url'ye ilet

@Body RequestBody key

4

Bu kadar çaba sarf ettikten sonra, temel farkın as parametresi JsonObjectyerine göndermeniz gerektiğidir JSONObject.


Ben de aynı hatayı yapıyordum: p
Mehtab Ahmed

4

En iyi cevaba dayanarak, her istek için POJO yapmak zorunda kalmayacak bir çözümüm var.

Örnek, ben bu JSON göndermek istiyorum.

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

sonra böyle bir ortak sınıf oluşturmak:

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<>();
    }
}

Sonunda, bir json'a ihtiyacım olduğunda

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

Ek açıklama olarak işaretlenen istek @BodyRetrofit'e geçebilir.


4

Ekstra sınıflar oluşturmak veya kullanmak JSONObjectistemiyorsanız a HashMap.

Retrofit arayüzü:

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

Aramak:

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'te ham json göndermek için gereken şeyler.

1) Aşağıdaki üstbilgiyi eklediğinizden ve yinelenen diğer üstbilgileri kaldırdığınızdan emin olun. Çünkü, Retrofit'in resmi belgelerinde özellikle

Başlıkların birbirlerinin üzerine yazmadığını unutmayın. Aynı ada sahip tüm başlıklar isteğe dahil edilecektir.

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

2) a. Bir dönüştürücü fabrikası kullanıyorsanız, json'unuzu String, JSONObject, JsonObject ve hatta POJO olarak geçirebilirsiniz. Ayrıca kontrol ettim, sahip ScalarConverterFactoryolmak gerekli değil sadece GsonConverterFactoryişi yapar.

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

2) b. Herhangi bir dönüştürücü fabrikası KULLANMAYINIZ, retrofit'in belgelerine göre okhttp3'ün RequestBody'sini KULLANMALIDIR.

Nesne ayrıca Retrofit örneğinde belirtilen bir dönüştürücü kullanılarak dönüştürülecektir. Hiçbir dönüştürücü eklenmezse, yalnızca RequestBody kullanılabilir.

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) Başarı !!


2

retrofit 2.6.2'nin şu anki sürümü için bu beni işe yarıyor ,

Her şeyden önce, java.lang.String nesnelerini metin / düz istek gövdelerine dönüştürmekle ilgilenen Gradle bağımlılıkları listemize bir Skaler Dönüştürücü eklememiz gerekir.

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

Ardından, Retrofit oluşturucumuza bir dönüştürücü fabrikası geçirmemiz gerekiyor. Daha sonra Retrofit'e servise iletilen @Body parametresini nasıl dönüştüreceğini söyleyecektir.

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

Not: Güçlendirme oluşturucumda iki dönüştürücüm var Gsonve Scalarsher ikisini de kullanabilirsiniz, ancak Json gövdesini göndermek için odaklanmamız gerekiyor, Scalarsbu yüzden Gsonkaldırmanız gerekmiyorsa

Sonra bir String body parametresi ile sonradan servis uyarlama.

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

Ardından JSON gövdesini oluşturun

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

Hizmetinizi arayın

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

2

Solution Çalışma Çözümü ✅✅✅✅✅✅✅✅✅✅✅✅

Bunu oluştururken OkHttpClient Retrofit için kullanılacaktır.

böyle bir Durdurucu ekleyin.

 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()

Artık reklam her Uyarlama aramanın URL ve istek gövdesi kaydedilir içinde Logcat. Filtreleme ölçütü"gsonrequest"


1

Bunu denedim: Retrofit örneğinizi oluştururken, bu dönüştürücü fabrikasını sonradan oluşturucuya ekleyin:

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

1

Sorunumu TommySM cevabına göre çözdüm (yukarıya bakınız). Ancak giriş yapmam gerekmedi, https GraphQL API'sini test etmek için Retrofit2 kullandım:

  1. BaseResponse sınıfımı json ek açıklamaları (import jackson.annotation.JsonProperty) yardımıyla tanımladı.

    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. Arayüzde çağrı prosedürü tanımlandı:

    @POST("/api/apiname")
    Call<BaseResponse> apicall(@Body RequestBody params);
  3. Test gövdesinde apicall olarak adlandırılır: MyRequest türünde bir değişken oluşturun (örneğin "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

Burada verilen cevaplar hakkında daha fazla netlik için, genişletme işlevlerini bu şekilde kullanabilirsiniz. Bu sadece Kotlin kullanıyorsanız

MediaType ve RequestBodycom.squareup.okhttp3:okhttp:4.0.1 nesnelerini oluşturmak için daha eski yöntemleri kullanıyorsanız , kullanımdan kaldırılmıştır ve KOTLIN .

Dizelerinizden bir MediaType nesnesi ve ResponseBody nesnesi almak için uzantı işlevlerini kullanmak istiyorsanız , öncelikle aşağıdaki satırları bunları kullanmayı beklediğiniz sınıfa ekleyin.

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

Artık doğrudan MediaType nesnesini bu şekilde alabilirsiniz

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

RequestBody nesnesini almak için önce bir dizeye bu şekilde göndermek istediğiniz JSONObject öğesini dönüştürün. MediaType nesnesini ona iletmeniz gerekir.

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

0

Kodun altına yazdığım verileri almak ve almak için voleybolu ve güçlendirme hızını karşılaştırmak istedim (güçlendirme kısmı için)

ilk bağımlılık:

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

Sonra arayüz:

 public interface IHttpRequest {

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

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

ve verileri sunucuya göndermek için parametreleri ayarlama işlevi (MainActivity'de):

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) {

        }
    });

}

Ve benim durumumda Retrofit'i voleyboldan daha hızlı buldum.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.