Comment afficher raw JSON entier dans le corps d'une demande de modification?

cette question a peut-être déjà été posée, mais non elle n'a pas reçu de réponse définitive. Comment exactement affiche-t-on un JSON entier brut dans le corps d'une demande de modification?

Voir question similaire ici . Ou est-ce que cette réponse est correcte qu'il doit être l'url du formulaire encodé et passé comme un champ ? J'espère vraiment que non, car les services auxquels je me connecte attendent simplement raw JSON dans le corps du post. Ils ne sont pas mis en place pour recherchez un champ particulier pour les données JSON.

je veux juste clarifier cela avec le restperts une fois pour toutes. Une personne a répondu de ne pas utiliser la modernisation. L'autre n'était pas certain de la syntaxe. Un autre pense que oui, il peut être fait, mais seulement si sa forme url-encodé et placé dans un champ (ce n'est pas acceptable dans mon cas). Non, Je ne peux pas RE-code tous les services pour mon client Android. Et oui, c'est très courant dans les grands projets de post raw JSON au lieu de passer le contenu JSON comme valeur de propriété de champ. Allons droit au but et passons à autre chose. Est-ce que quelqu'un peut montrer la documentation ou l'exemple qui montre comment cela est fait? Ou donnez une raison valable pour laquelle cela peut / ne devrait pas être fait.

mise à jour: une chose que je peux dire avec 100% de certitude. Vous pouvez le faire dans Google Volley. Il est intégré. On peut faire ça en rénovation?

195
demandé sur Community 2014-01-28 10:40:16

10 réponses

l'annotation @Body définit un corps de requête unique.

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

puisque Retrofit utilise Gson par défaut, les instances FooRequest seront sérialisées en JSON comme seul corps de la requête.

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

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

appel avec:

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

donnera le corps suivant:

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

le Gson docs ont beaucoup plus sur le fonctionnement de la sérialisation des objets.

maintenant, si vous voulez vraiment envoyer " raw " JSON comme le corps vous-même (mais s'il vous plaît utilisez Gson pour cela!) vous pouvez toujours utiliser TypedInput :

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

TypedInput est défini comme " données binaires avec un type mime associé.". Il y a deux façons d'envoyer facilement des données brutes avec la déclaration ci-dessus:

  1. utilisation TypedByteArray pour envoyer des octets brutes et le JSON type mime:

    String json = "{\"foo\":\"kit\",\"bar\":\"kat\"}";
    TypedInput in = new TypedByteArray("application/json", json.getBytes("UTF-8"));
    FooResponse response = foo.postRawJson(in);
    
  2. sous-classe Typographie pour créer une TypedJsonString classe:

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

    Et ensuite utiliser une instance de cette classe similaire à #1.

367
répondu Jake Wharton 2014-01-29 05:53:33

au lieu de classes, nous pouvons aussi utiliser directement le HashMap<String, Object> pour envoyer les paramètres du corps par exemple

interface Foo {
  @POST("/jayson")
  FooResponse postJson(@Body HashMap<String, Object> body);
}
113
répondu Boopathi 2016-05-04 06:46:27

Oui je sais qu'il est tard, mais quelqu'un en profiterait probablement.

Utilisant Retrofit2:

j'ai rencontré ce problème hier soir lors de la migration de Volley à Retrofit2 (et comme L'indique OP, cela a été construit directement dans Volley avec JsonObjectRequest ), et bien que la réponse de Jake est la bonne pour Retrofit1.9 , Retrofit2 doesn't have TypedString .

My cas nécessaire d'envoyer un Map<String,Object> qui pourrait contenir des valeurs nulles, converti en un JSONObject (qui ne volera pas avec @FieldMap , pas plus que les caractères spéciaux, certains seront convertis), donc suivant @ bnorms hint ,et comme indiqué par carré :

un objet peut être spécifié pour être utilisé comme un corps de requête HTTP avec l'annotation @Body.

l'objet sera également converti en utilisant un convertisseur spécifié sur la Rénovation de l'instance. Si aucun convertisseur n'est ajouté, seul RequestBody peut être utilisé.

donc c'est une option utilisant RequestBody et ResponseBody :

dans votre interface utilisez @Body avec RequestBody

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

dans votre point d'appel créer un RequestBody , en indiquant Qu'il est MediaType, et en utilisant JSONObject pour convertir votre carte au format approprié:

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

J'espère que Aide à n'importe qui!


une élégante version Kotlin de ce qui précède, pour permettre l'Abstraction des paramètres de la conversion JSON dans le reste de votre code d'application:

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

}
110
répondu TommySM 2018-09-18 13:07:06

Dans Retrofit2 , Lorsque vous voulez envoyer vos paramètres en raw, vous devez utiliser Scalaires .

ajoutez d'abord ceci dans votre Grad:

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'

Votre Interface

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

}

activité

   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) {
    }
}
48
répondu Jonathan Nolasco Barrientos 2017-11-12 20:49:12

L'utilisation de JsonObject est la façon dont il est:

  1. créez votre interface comme ceci:

      public interface laInterfaz{ 
           @POST("/bleh/blah/org")
           void registerPayer(@Body JsonObject bean, Callback<JsonObject> callback);
     }
    
  2. font le JsonObject d'après la structure 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. Appeler le service:

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

    };

et que son! Dans mon opinion personnelle, c'est beaucoup mieux que de faire des pojos et de travailler avec le désordre de la classe. C'est beaucoup plus propre.

31
répondu superUser 2015-09-16 12:24:47

j'aime particulièrement la suggestion de Jake de la TypedString sous-classe au-dessus de . Vous pouvez en effet créer une variété de sous-classes basées sur les types de données POST que vous prévoyez de promouvoir, chacune avec son propre ensemble personnalisé de modifications cohérentes.

vous avez aussi l'option d'ajouter une annotation d'en-tête à vos méthodes de publication JSON POST dans votre API Retrofit...""

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

... mais l'utilisation d'une sous-classe est plus évidemment auto-documentée.

@POST("/json/foo/bar")
Response fubar( @Body TypedJsonString jsonBody ) ;
7
répondu zerobandwidth 2017-05-23 12:18:22

après tant d'efforts, trouvé que la différence de base est que vous devez envoyer le JsonObject au lieu de JSONObject comme paramètre.

3
répondu umair151 2018-03-05 18:03:03

1)Ajouter des dépendances -

 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) faire de l'Api du Gestionnaire de classe

    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) Faire des classes de haricots à partir de JSON schema 2 pojo

Souvenez-vous

- Langue cible: Java -Source type : JSON -Annotation style : Gson -sélectionnez Inclure les getters et les setters -vous pouvez également sélectionner autoriser des propriétés

http://www.jsonschema2pojo.org/

4)make interface from api calling

    public interface Webservices {

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

}

si vous avez un formulaire-paramètres de données alors ajouter au-dessous de la ligne

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

Autre façon pour les données de formulaire vérification des paramètres de cette lien

5)faire JsonObject pour le passage dans le corps comme paramètre

 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) appeler Api comme ceci

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();
    }
}
3
répondu AD 10 2018-03-14 09:41:01

basé sur la réponse du haut, j'ai une solution pour ne pas avoir à faire des POJOs pour chaque demande.

exemple, je veux poster ce JSON.

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

alors, je crée une classe commune comme celle-ci:

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

enfin, quand j'ai besoin d'un json

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

la demande annotée @Body peut alors passer à la mise à niveau.

2
répondu wjploop 2018-09-01 04:43:59

utiliser ce qui suit pour envoyer 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());

et passez-le à l'url

@Body RequestBody key
0
répondu Mahesh Pandit 2018-08-02 19:27:13