70 votes

Retrofit 2 : Obtenir JSON du corps de la réponse

Je veux obtenir une chaîne json de mon api en utilisant retrofit 2, je n'ai pas de problème en utilisant retrofit 1 pour obtenir ce json, mais en utilisant retrofit 2, j'obtiens nul pour moi.

Voici à quoi ressemble mon json

{"id":1,"Username":"admin","Level":"Administrator"}

Voici mon API

@FormUrlEncoded
@POST("/api/level")
Call<ResponseBody> checkLevel(@Field("id") int id);

Voici à quoi ressemble mon code

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(Config.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        Api api = retrofit.create(Api.class);
        Call<ResponseBody> call = api.checkLevel(1);
        call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                JsonObject post = new JsonObject().get(response.body().toString()).getAsJsonObject();
                    if (post.get("Level").getAsString().contains("Administrator")) {

                    }
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
            }
        });

Je suis nouveau dans retrofit 2 et en utilisant le code ci-dessus, cela fait toujours planter mes applications car response.body().toString() renvoie un résultat nul.

Merci de m'indiquer comment récupérer cette chaîne json afin de la convertir en JsonObject.

0 votes

0 votes

Vous ne pouvez accéder à response.body.string() qu'une seule fois, après quoi il renverra null.

0 votes

Response.body().toString() Je l'ai changé en try{ String result = response.body().string() ; }catch(Exception e){ e.printStackTrace() ; } Cela a fonctionné pour moi !

64voto

Sushil Kumar Points 4456

Utiliser cette lien pour convertir votre JSON en POJO avec les options sélectionnées dans l'image ci-dessous

enter image description here

Vous obtiendrez une classe POJO pour votre réponse comme ceci

public class Result {

    @SerializedName("id")
    @Expose
    private Integer id;
    @SerializedName("Username")
    @Expose
    private String username;
    @SerializedName("Level")
    @Expose
    private String level;

    /**
    * 
    * @return
    * The id
    */
    public Integer getId() {
        return id;
    }

    /**
    * 
    * @param id
    * The id
    */
    public void setId(Integer id) {
        this.id = id;
    }

    /**
    * 
    * @return
    * The username
    */
    public String getUsername() {
        return username;
    }

    /**
    * 
    * @param username
    * The Username
    */
    public void setUsername(String username) {
        this.username = username;
    }

    /**
    * 
    * @return
    * The level
    */
    public String getLevel() {
        return level;
    }

    /**
    * 
    * @param level
    * The Level
    */
    public void setLevel(String level) {
        this.level = level;
    }

}

et utiliser l'interface comme suit :

@FormUrlEncoded
@POST("/api/level")
Call<Result> checkLevel(@Field("id") int id);

et l'appeler ainsi :

Call<Result> call = api.checkLevel(1);
call.enqueue(new Callback<Result>() {
    @Override
    public void onResponse(Call<Result> call, Response<Result> response) { 
     if(response.isSuccessful()){
        response.body(); // have your all data
        int id =response.body().getId();
        String userName = response.body().getUsername();
        String level = response.body().getLevel();
        }else   Toast.makeText(context,response.errorBody().string(),Toast.LENGTH_SHORT).show(); // this will tell you why your api doesnt work most of time

    }

    @Override
    public void onFailure(Call<Result> call, Throwable t) {
     Toast.makeText(context,t.toString(),Toast.LENGTH_SHORT).show(); // ALL NETWORK ERROR HERE

    }
});

et utiliser les dépendances dans Gradle

compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-gson:2.+'

NOTE : L'erreur se produit parce que vous avez transformé votre JSON en POJO (par l'utilisation de addConverterFactory(GsonConverterFactory.create()) dans le cadre de la modernisation). Si vous voulez une réponse en JSON, supprimez l'élément addConverterFactory(GsonConverterFactory.create()) de Retrofit. Si ce n'est pas le cas, utilisez la solution ci-dessus

0 votes

La solution la plus proche que je cherchais mais la nouvelle version nous donne public void onResponse(retrofit.Response<ReturnSignUp> response, Retrofit retrofit) mais mes modèles sont comme suit hastebin.com/cobezeyoyi.java et response.body(). ne donne pas mes méthodes get...

0 votes

Pour la question de l'OP, le POJO est correct. Si vous avez une question différente comme celle-ci, vous devez créer des méthodes getter et setter, qui ne sont pas présentes dans votre POJO.

0 votes

Comment créer une classe POJO qui contient des objets json à l'intérieur d'autres objets json ?

52voto

Sunil Points 1487

Si vous souhaitez obtenir la totalité de la réponse au format JSON, essayez ceci :

J'ai essayé une nouvelle méthode pour obtenir une réponse complète du serveur au format JSON sans créer de classe de modèle. Je n'utilise aucune classe de modèle pour obtenir des données du serveur. parce que je ne sais pas quelle réponse je recevrai ou qu'elle peut changer en fonction des besoins.

il s'agit d'une réponse JSON :

{"contacts": [
    {
        "id": "c200",
        "name": "sunil",
        "email": "email@gmail.com",
        "address": "xx-xx-xxxx,x - street, x - country",
        "gender" : "male",
        "phone": {
            "mobile": "+91 0000000000",
            "home": "00 000000",
            "office": "00 000000"
        }
    },
    {
        "id": "c201",
        "name": "Johnny Depp",
        "email": "johnny_depp@gmail.com",
        "address": "xx-xx-xxxx,x - street, x - country",
        "gender" : "male",
        "phone": {
            "mobile": "+91 0000000000",
            "home": "00 000000",
            "office": "00 000000"
        }
    },
    .
    .
    .
]}
  1. Dans votre interface API, modifiez le paramètre

    public interface ApiInterface {
    @POST("/index.php/User/login")//your api link 
    @FormUrlEncoded
    Call<Object> getmovies(@Field("user_email_address") String title,
                    @Field("user_password") String body);
    }
  2. dans votre activité principale où vous appelez cette

    ApiInterface apiService =
            ApiClient.getClient().create(ApiInterface.class);
    
    Call call = apiService.getmovies("a@gmail.com","123456");
    call.enqueue(new Callback() {
        @Override
        public void onResponse(Call call, Response response) {
            Log.e("TAG", "response 33: "+new Gson().toJson(response.body()) );
        }
    
        @Override
        public void onFailure(Call call, Throwable t) {
            Log.e("TAG", "onFailure: "+t.toString() );
            // Log error here since request failed
        }
    });
  3. Ensuite, vous pouvez normalement obtenir des paramètres en utilisant un objet JSON ou un tableau JSON.

Sortie enter image description here

30voto

Utiliser ceci pour obtenir la chaîne de caractères

String res = response.body().string();

au lieu de

String res = response.body().toString();

et toujours vérifier que le corps de la réponse n'est pas nul avant de le convertir en chaîne de caractères.

if(response.body() != null){
     //do your stuff   
}

2 votes

Cela ne fonctionne pas... le corps de la réponse est une valeur unique qui ne peut être consommée qu'une seule fois. Ainsi, lors du débogage, il y a un appel "derrière la scène" depuis l'inspecteur et le corps est toujours vide.

0 votes

response.body() a déjà construit un POJO pour votre appel de rétrofit, qui n'a pas nécessairement de string() méthode.

5voto

Mahesh Pandit Points 57

Ajouter une dépendance pour retrofit2

compile 'com.google.code.gson:gson:2.6.2'
compile 'com.squareup.retrofit2:retrofit:2.0.2'
compile 'com.squareup.retrofit2:converter-gson:2.0.2'

créer une classe pour l'url de base

public class ApiClient     
{
public static final String BASE_URL = "base_url";

private static Retrofit retrofit = null;

public static Retrofit getClient() {
    if (retrofit==null) {
        retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
    }
    return retrofit;
}

}

Ensuite, créer une classe modèle pour obtenir la valeur

public class ApprovalModel {

@SerializedName("key_parameter")
private String approvalName;
public String getApprovalName() {
    return approvalName;
}
}

créer une classe d'interface

public interface ApiInterface { 
@GET("append_url")
Call<CompanyDetailsResponse> getCompanyDetails();
}

ensuite dans la classe principale

 if(Connectivity.isConnected(mContext)){
            final ProgressDialog mProgressDialog = new ProgressDialog(mContext);
            mProgressDialog.setIndeterminate(true);
            mProgressDialog.setMessage("Loading...");
            mProgressDialog.show();

            ApiInterface apiService =
                    ApiClient.getClient().create(ApiInterface.class);

            Call<CompanyDetailsResponse> call = apiService.getCompanyDetails();
            call.enqueue(new Callback<CompanyDetailsResponse>() {
                @Override
                public void onResponse(Call<CompanyDetailsResponse>call, Response<CompanyDetailsResponse> response) {
                    mProgressDialog.dismiss();
                    if(response!=null && response.isSuccessful()) {
                        List<CompanyDetails> companyList = response.body().getCompanyDetailsList();

                        if (companyList != null&&companyList.size()>0) {
                            for (int i = 0; i < companyList.size(); i++) {
                                Log.d(TAG, "" + companyList.get(i));
                            }
                         //get values
                        }else{
                            //show alert not get value
                        }
                    }else{
                        //show error message

                    }
                }

                @Override
                public void onFailure(Call<CompanyDetailsResponse>call, Throwable t) {
                    // Log error here since request failed
                    Log.e(TAG, t.toString());
                    mProgressDialog.dismiss();
                }
            });
        }else{
            //network error alert box

        }

2voto

John O'Reilly Points 5188

Une meilleure approche est de laisser Retrofit générer des POJO pour vous à partir du json (en utilisant gson ). La première chose à faire est d'ajouter .addConverterFactory(GsonConverterFactory.create()) lors de la création de votre Retrofit instance. Par exemple, si vous avez un User (comme indiqué ci-dessous) qui correspond à votre json, alors votre api retrofit pourrait renvoyer Call<User>

class User {
    private String id;
    private String Username;
    private String Level;
    ...
}

0 votes

Je suis désolé de ne pas être d'accord, mais Retrofit ne génère pas de POJO à partir de json, mais seulement un objet basé sur un POJO préalablement déclaré.

1 votes

Oui, c'est ce que je voulais dire... "générer une instance POJO" aurait été plus clair.

0 votes

Juste une note : vous devez ajouter 'com.squareup.retrofit2:converter-gson:<version>' à vos dépendances pour utiliser ce convertisseur.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X