Этот вопрос, возможно, задавался раньше, но нет, на него не было окончательного ответа. Как именно можно разместить необработанный JSON целиком в теле запроса Retrofit?
Смотрите аналогичный вопрос здесь . Или этот ответ правильный, что он должен быть закодирован в форме URL и передан в виде поля ? Я действительно надеюсь, что нет, так как службы, к которым я подключаюсь, просто ожидают сырой JSON в теле поста. Они не настроены на поиск определенного поля для данных JSON.
Я просто хочу уточнить это с отдыхающими раз и навсегда. Один человек ответил, что не следует использовать Retrofit. Другой не был уверен в синтаксисе. Другой думает, что да, это может быть сделано, но только если его форма закодирована и размещена в поле (это не приемлемо в моем случае). Нет, я не могу перекодировать все сервисы для моего Android-клиента. И да, в крупных проектах очень распространено публиковать необработанный JSON вместо передачи содержимого JSON в качестве значений свойств поля. Давайте сделаем это правильно и продолжим. Может кто-то указать на документацию или пример, который показывает, как это делается? Или укажите вескую причину, по которой это можно / не следует делать.
ОБНОВЛЕНИЕ: Одна вещь, которую я могу сказать со 100% уверенностью. Вы можете сделать это в Google Volley. Он построен прямо в. Можем ли мы сделать это в Retrofit?
RequestBody
таким ->RequestBody body = RequestBody.create(MediaType.parse("text/plain"), text);
для подробного ответа futurestud.io/tutorials/…Ответы:
@Body
Аннотаций определяет единое тело запроса.Поскольку Retrofit по умолчанию использует Gson,
FooRequest
экземпляры будут сериализованы как JSON в качестве единственного тела запроса.Звонить с:
Дадим следующее тело:
В документации Gson гораздо больше о том, как работает сериализация объектов.
Теперь, если вы действительно хотите отправить «сырой» JSON как тело самостоятельно (но для этого используйте Gson!), Вы все равно можете использовать
TypedInput
:TypedInput определяется как «Двоичные данные со связанным типом MIME». Есть два способа легко отправить необработанные данные с помощью вышеуказанной декларации:
Используйте TypedByteArray для отправки необработанных байтов и тип MIME JSON:
Подкласс TypedString для создания
TypedJsonString
класса:А затем используйте экземпляр этого класса, похожий на # 1.
источник
TypedString
так как он был удален?RequestBody
для создания необработанного тела.java.lang.IllegalArgumentException: Unable to create @Body converter for class MatchAPIRequestBody (parameter #1)
Вместо классов мы также можем напрямую использовать, например,
HashMap<String, Object>
для отправки параметров телаисточник
IllegalArgumentException: Unable to create @Body converter for java.util.HashMap<java.lang.String, java.lang.Object>
с Моши. Я думаю, что Gson нужен для того, чтобы это работалоДа, я знаю, что уже поздно, но кто-то, вероятно, выиграет от этого.
Использование Retrofit2:
Вчера вечером я столкнулся с этой проблемой при переходе с Volley на Retrofit2 (и, как утверждает OP, он был встроен прямо в Volley
JsonObjectRequest
), и хотя ответ Джейка является правильным для Retrofit1.9 , Retrofit2 не имеетTypedString
.В моем случае требовалась отправка a,
Map<String,Object>
который мог бы содержать некоторые нулевые значения, конвертированные в JSONObject (который не будет летать@FieldMap
, также не используются специальные символы, некоторые конвертировались), поэтому следовали подсказке @bnorms и как указано в Square :Так что это вариант с использованием
RequestBody
иResponseBody
:В вашем интерфейсе используйте
@Body
сRequestBody
В вашей точке вызова создайте
RequestBody
, указав его MediaType, и используйте JSONObject для преобразования вашей карты в правильный формат:Надеюсь, это поможет никому!
Элегантная версия Kotlin выше, позволяющая абстрагировать параметры от преобразования JSON в остальной части кода вашего приложения:
источник
JsonObjectRequest
, все, что вам нужно сделать, это это. Хороший ответ.post a null value
найти свойство в requestBody, которое иначе игнорировалось.jsonParams.put("code", some_code);
в третьей строке?В Retrofit2 , когда вы хотите отправить свои параметры в сыром виде, вы должны использовать скаляры .
сначала добавьте это в ваш gradle:
Ваш интерфейс
Деятельность
источник
GsonConverterFactory
,.toString()
это не обязательно. Вы можете объявитьCall<User> getUser(@Body JsonObject body);
использованиеJsonObject
вместоJSONObject
и передатьparamObject
напрямую. Это будет работать просто отлично.Использование
JsonObject
это так:Создайте свой интерфейс так:
Сделайте JsonObject в соответствии со структурой jsons.
Позвоните в сервис:
И это его! По моему личному мнению, это намного лучше, чем делать поно и работать с классом. Это намного чище.
источник
Мне особенно нравится предложение Джейка
TypedString
подкласса выше . Вы действительно можете создать множество подклассов, основанных на видах POST-данных, которые вы планируете выдвигать, каждый со своим собственным набором согласованных настроек.У вас также есть возможность добавить аннотацию заголовка к вашим методам JSON POST в вашем Retrofit API…
... но использование подкласса более очевидно самодокументируется.
источник
1) Добавить зависимости-
2) сделать класс Api Handler
3) создать бобовые классы из схемы Json 2 pojo
http://www.jsonschema2pojo.org/
4) сделать интерфейс вызова API
5) сделать JsonObject для передачи в тело в качестве параметра
6) Позвони в Api вот так
источник
Я обнаружил, что когда вы используете составной объект в качестве
@Body
параметров, он не может хорошо работать с RetrofitGSONConverter
(при условии, что вы используете это). Вы должны использовать,JsonObject
а неJSONObject
при работе с этим, он добавляет,NameValueParams
не будучи многословным об этом - вы можете увидеть это, только если добавите еще одну зависимость от перехватчика регистрации и других махинаций.Так что я нашел лучший подход к решению этой проблемы
RequestBody
. Вы превращаете свой объект вRequestBody
простой вызов API и запускаете его. В моем случае я конвертирую карту:и это вызов:
источник
Добавьте ScalarsConverterFactory для модернизации:
в градле:
ваша модернизация:
измените параметр @Body интерфейса вызова на String, не забудьте добавить
@Headers("Content-Type: application/json")
:Теперь вы можете опубликовать сырой JSON.
источник
Вы можете использовать hashmap, если не хотите создавать класс pojo для каждого вызова API.
А потом отправь вот так
источник
используйте следующее, чтобы отправить JSON
и передать его URL
источник
После стольких усилий выяснилось, что основное отличие заключается в том, что вам нужно отправлять
JsonObject
вместоJSONObject
параметра.источник
Основываясь на верхнем ответе, у меня есть решение не делать POJO для каждого запроса.
Пример, я хочу опубликовать этот JSON.
Затем я создаю общий класс, как это:
Наконец, когда мне нужен JSON
Запрос, помеченный аннотацией,
@Body
затем может перейти на Retrofit.источник
Если вы не хотите создавать дополнительные классы или использовать их,
JSONObject
вы можете использоватьHashMap
.Модифицированный интерфейс:
Вызов:
источник
Вещи, необходимые для отправки сырой JSON в Retrofit.
1) Обязательно добавьте следующий заголовок и удалите любой другой дублирующий заголовок. Поскольку в официальной документации Retrofit они специально упоминают
2) а. Если вы используете фабрику преобразователей, вы можете передать свой json как String, JSONObject, JsonObject и даже POJO. Также проверили, не имея
ScalarConverterFactory
толькоGsonConverterFactory
делает работу.2) б. Если вы НЕ используете какую-либо фабрику преобразователей, тогда вы ДОЛЖНЫ использовать RequestBody от okhttp3, как сказано в документации Retrofit:
3) Удачи !!
источник
Это то, что работает у меня для текущей версии
retrofit
2.6.2 ,Прежде всего, нам нужно добавить Scalars Converter в список наших зависимостей Gradle, который позаботится о преобразовании объектов java.lang.String в текстовые / обычные тела запросов,
Затем нам нужно передать конвертерный завод нашему строителю. Позже он сообщит Retrofit, как преобразовать параметр @Body, переданный службе.
Затем модифицируйте сервис с параметром тела String.
Затем создайте тело JSON
Позвоните в сервис
источник
✅✅✅✅✅✅✅✅✅✅✅✅ Рабочий раствор ✅✅✅✅✅✅✅✅✅✅✅✅
При создании
OkHttpClient
это будет использоваться для модернизации.добавить перехватчик, как это.
Теперь URL и тело запроса каждого вашей ДООСНАСТКА вызова будет зарегистрировано в
Logcat
. Фильтровать это по"gsonrequest"
источник
Я попробовал это: Когда вы создаете свой экземпляр Retrofit, добавьте эту фабрику конвертеров в построитель Retrofit:
источник
Решил мою проблему на основе ответа TommySM (см. Предыдущий). Но мне не нужно было входить в систему, я использовал Retrofit2 для тестирования https GraphQL API следующим образом:
Определил мой класс BaseResponse с помощью аннотаций json (импорт jackson.annotation.JsonProperty).
Определена процедура вызова в интерфейсе:
Вызывается apicall в теле теста: создайте переменную типа MyRequest (например, «myLittleRequest»).
источник
Для большей ясности в ответах, приведенных здесь, вы можете использовать функции расширения. Это только если вы используете Kotlin
Если вы используете
com.squareup.okhttp3:okhttp:4.0.1
более старые методы создания объектов MediaType и RequestBody , они устарели и не могут использоваться в Kotlin .Если вы хотите использовать функции расширения для получения объекта MediaType и объекта ResponseBody из ваших строк, сначала добавьте следующие строки в класс, в котором вы ожидаете их использовать.
Теперь вы можете напрямую получить объект MediaType таким образом
Чтобы получить объект RequestBody, сначала преобразуйте JSONObject, который вы хотите отправить в строку таким образом. Вы должны передать объект mediaType ему.
источник
Я хотел сравнить скорость залпа и модификации для отправки и получения данных, которые я написал ниже кода (для части модернизации)
первая зависимость:
Тогда интерфейс:
и функция для установки параметров для отправки данных на сервер (в MainActivity):
И я нашел Retrofit быстрее, чем залп в моем случае.
источник