Как разместить в исходном виде запрос на модификацию необработанного целого JSON?


285

Этот вопрос, возможно, задавался раньше, но нет, на него не было окончательного ответа. Как именно можно разместить необработанный JSON целиком в теле запроса Retrofit?

Смотрите аналогичный вопрос здесь . Или этот ответ правильный, что он должен быть закодирован в форме URL и передан в виде поля ? Я действительно надеюсь, что нет, так как службы, к которым я подключаюсь, просто ожидают сырой JSON в теле поста. Они не настроены на поиск определенного поля для данных JSON.

Я просто хочу уточнить это с отдыхающими раз и навсегда. Один человек ответил, что не следует использовать Retrofit. Другой не был уверен в синтаксисе. Другой думает, что да, это может быть сделано, но только если его форма закодирована и размещена в поле (это не приемлемо в моем случае). Нет, я не могу перекодировать все сервисы для моего Android-клиента. И да, в крупных проектах очень распространено публиковать необработанный JSON вместо передачи содержимого JSON в качестве значений свойств поля. Давайте сделаем это правильно и продолжим. Может кто-то указать на документацию или пример, который показывает, как это делается? Или укажите вескую причину, по которой это можно / не следует делать.

ОБНОВЛЕНИЕ: Одна вещь, которую я могу сказать со 100% уверенностью. Вы можете сделать это в Google Volley. Он построен прямо в. Можем ли мы сделать это в Retrofit?


7
Пост Джейка Уортона правильный! Отметить как ответ!
edotassi

1
Вы могли бы использовать jsonObject лучше.
superUser

отлично работает с RequestBodyтаким -> RequestBody body = RequestBody.create(MediaType.parse("text/plain"), text);для подробного ответа futurestud.io/tutorials/…
Kidus Tekeste

Ответы:


460

@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». Есть два способа легко отправить необработанные данные с помощью вышеуказанной декларации:

  1. Используйте TypedByteArray для отправки необработанных байтов и тип MIME JSON:

    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
Очень хорошо, однако, в любом случае, чтобы сделать это, не делая pojos?
суперпользователь

28
Это не работает при модернизации 2. Классы TypedInput и TypedString были удалены.
Ахмед Хегазы

2
@jakewharton Что мы можем сделать, TypedStringтак как он был удален?
Джаред Берроуз

12
Для Retrofit2 вы можете использовать RequestBodyдля создания необработанного тела.
bnorm

4
Я получаю это исключениеjava.lang.IllegalArgumentException: Unable to create @Body converter for class MatchAPIRequestBody (parameter #1)
Shajeel Afzal

156

Вместо классов мы также можем напрямую использовать, например, HashMap<String, Object>для отправки параметров тела

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

2
В то же время вы можете создать Hash map, например, HashMap <String, Object>, это может быть возможно для создания своего рода сложных массивов и объектов JSON.
ученик

2
Это отлично, если вы не хотите быть привязанным к какому-либо POJO.
Тим

2
@ Нет, вы не можете отправить объект json, используя модификацию ... вы придерживаетесь pojo или моего ответа ... это характер модернизации ,
ученик

5
Я получаю IllegalArgumentException: Unable to create @Body converter for java.util.HashMap<java.lang.String, java.lang.Object>с Моши. Я думаю, что Gson нужен для того, чтобы это работало
osrl

2
При использовании Kotlin используйте хеш-карту <String, Any>
peresisUser

149

Да, я знаю, что уже поздно, но кто-то, вероятно, выиграет от этого.

Использование Retrofit2:

Вчера вечером я столкнулся с этой проблемой при переходе с Volley на Retrofit2 (и, как утверждает OP, он был встроен прямо в Volley JsonObjectRequest), и хотя ответ Джейка является правильным для Retrofit1.9 , Retrofit2 не имеет TypedString.

В моем случае требовалась отправка a, Map<String,Object>который мог бы содержать некоторые нулевые значения, конвертированные в JSONObject (который не будет летать @FieldMap, также не используются специальные символы, некоторые конвертировались), поэтому следовали подсказке @bnorms и как указано в Square :

Объект может быть указан для использования в качестве тела HTTP-запроса с аннотацией @Body.

Объект также будет преобразован с использованием преобразователя, указанного в экземпляре 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())

}

2
Да, я вижу много сложных ответов повсюду для этого. Если вы используете Retrofit2 и хотите сделать залп JsonObjectRequest, все, что вам нужно сделать, это это. Хороший ответ.
VicVu

2
Модернизация добавляет ключ с именем «nameValuePairs» в начало всех объектов json. Как я могу удалить это @TommySM
nr5

1
Спасибо! Это решило мою проблему. Теперь я могу отправлять JSONObject напрямую, не создавая POJO.
Эрфан GLMPR

1
Это единственное решение, которое помогло мне post a null valueнайти свойство в requestBody, которое иначе игнорировалось.
Шубрал

Я знаю, что опаздываю, но что jsonParams.put("code", some_code);в третьей строке?
Навин Нираула

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

10
Хитрость в этом заключается в использовании скалярного адаптера до Gson, иначе Gson обернет ваш сериализованный вручную JSON в строку.
TWiStErRob

2
jonathan-nolasco-barrientos, вы должны изменить .baseUrl (ApiInterface.ENDPOINT) на .baseUrl (ApiInterface.URL_BASE)
Милад Ахмади

2
Когда вы используете GsonConverterFactory, .toString()это не обязательно. Вы можете объявить Call<User> getUser(@Body JsonObject body);использование JsonObjectвместо JSONObjectи передать paramObjectнапрямую. Это будет работать просто отлично.
Игорь де Лоренци

1
@IgordeLorenzi решает мою проблему, так как я использую весеннюю загрузку, чтобы получить только json JsonObject из gson работает нормально
haidarvm

1
@IgordeLorenzi Есть ли разница, какую лучше использовать JSONObject или JsonObject со скалярами.
Сумит Шукла

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. какую аннотацию я могу использовать выше, чтобы проверить это?
Али Гюрелли

1
Как видно из приведенного выше примера ... JsonObject, как объект, не использует аннотации. В вашем случае, если вы не хотите отправлять определенное значение, вы можете просто не добавлять его в качестве свойства ...
superUser

1
Я имею в виду, я не хочу отправлять значение, которое объявлено в классе. Кстати, я решил проблему. Там была аннотация для того, имя которого выставить.
Али Гюрелли

2
Это самый гибкий способ. Вы можете создать свой объект json, даже если вы не знаете, сколько полей у вас будет, или даже если вы не знаете, что их имена +1 от меня
Стойчо Андреев

1
я получаю ошибку. для метода APIServices.signUpUser
Erum

11

Мне особенно нравится предложение Джейка TypedStringподкласса выше . Вы действительно можете создать множество подклассов, основанных на видах POST-данных, которые вы планируете выдвигать, каждый со своим собственным набором согласованных настроек.

У вас также есть возможность добавить аннотацию заголовка к вашим методам JSON POST в вашем Retrofit API…

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

... но использование подкласса более очевидно самодокументируется.

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

1
Спас день с ясным примером, используя TypedJsonString из предложения JW
miroslavign

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

Запомните
- Язык назначения: Java- Тип источника: JSON-Стиль аннотации: Gson -select Включить геттеры и сеттеры -также вы можете выбрать Разрешить дополнительные свойства

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

Другой способ для параметра формы данных проверить эту ссылку

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параметров, он не может хорошо работать с Retrofit 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

Вы можете использовать hashmap, если не хотите создавать класс pojo для каждого вызова API.

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

А потом отправь вот так

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

5

используйте следующее, чтобы отправить 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

После стольких усилий выяснилось, что основное отличие заключается в том, что вам нужно отправлять JsonObjectвместо JSONObjectпараметра.


Я также делал ту же ошибку: р
Мехтаб Ахмед

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затем может перейти на Retrofit.


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

Вещи, необходимые для отправки сырой JSON в Retrofit.

1) Обязательно добавьте следующий заголовок и удалите любой другой дублирующий заголовок. Поскольку в официальной документации Retrofit они специально упоминают

Обратите внимание, что заголовки не перезаписывают друг друга. Все заголовки с одинаковым именем будут включены в запрос.

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

2) а. Если вы используете фабрику преобразователей, вы можете передать свой json как String, 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) б. Если вы НЕ используете какую-либо фабрику преобразователей, тогда вы ДОЛЖНЫ использовать RequestBody от okhttp3, как сказано в документации Retrofit:

Объект также будет преобразован с использованием преобразователя, указанного в экземпляре 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 в текстовые / обычные тела запросов,

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

Затем нам нужно передать конвертерный завод нашему строителю. Позже он сообщит Retrofit, как преобразовать параметр @Body, переданный службе.

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

Примечание: в моем сборщике модификаций у меня есть два конвертера, Gsonи Scalarsвы можете использовать оба из них, но для отправки тела Json нам нужно сосредоточиться, Scalarsпоэтому, если вам не нужно Gsonего удалять

Затем модифицируйте сервис с параметром тела String.

@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

Я попробовал это: Когда вы создаете свой экземпляр Retrofit, добавьте эту фабрику конвертеров в построитель Retrofit:

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

1

Решил мою проблему на основе ответа TommySM (см. Предыдущий). Но мне не нужно было входить в систему, я использовал Retrofit2 для тестирования https GraphQL API следующим образом:

  1. Определил мой класс BaseResponse с помощью аннотаций json (импорт 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

Если вы используете 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)

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

        }
    });

}

И я нашел Retrofit быстрее, чем залп в моем случае.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.