Intereting Posts

Как выполнить POST-сырой целый JSON в теле запроса на доработку?

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

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

Я просто хочу прояснить это с помощью restpts раз и навсегда. Один человек ответил, что не использует «Дооснащение». Другой не был уверен в синтаксисе. Другой думает, да, это можно сделать, но только если его форма закодирована и помещена в поле (это неприемлемо в моем случае). Нет, я не могу перекодировать все службы для моего 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». Есть два способа легко отправить необработанные данные с указанным выше объявлением:

  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.

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

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

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

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

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

Моему случаю потребовалась отправка 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> map = 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... } }); 

Надеюсь, это поможет кому угодно!

Использование 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()); } 

    };

И это его! По моему личному мнению, это намного лучше, чем делать pojos и работать с классовым беспорядком. Это намного чище.

В Retrofit2 , Когда вы хотите отправить свои параметры в raw, вы должны использовать Scalars .

Сначала добавьте это в свой градл:

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

Мне особенно нравится предложение TypedString подкласса 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 ) ;