Impossible de créer un convertisseur pour ma classe dans la bibliothèque Android Retrofit

130

Im migrant de l'utilisation de Volley vers Retrofit, j'ai déjà la classe gson que j'ai utilisée auparavant pour convertir la réponse JSONObject en un objet qui implémente les annotations gson. Lorsque j'essaie de faire une demande http get à l'aide de la mise à niveau, mais que mon application se bloque avec cette erreur:

 Unable to start activity ComponentInfo{com.lightbulb.pawesome/com.example.sample.retrofit.SampleActivity}: java.lang.IllegalArgumentException: Unable to create converter for class com.lightbulb.pawesome.model.Pet
    for method GitHubService.getResponse

Je suis le guide du site de rénovation et je propose ces implémentations:

C'est mon activité où j'essaye d'exécuter la requête http rétro:

public class SampleActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sample);

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("**sample base url here**")
                .build();

        GitHubService service = retrofit.create(GitHubService.class);
        Call<Pet> callPet = service.getResponse("41", "40");
        callPet.enqueue(new Callback<Pet>() {
            @Override
            public void onResponse(Response<Pet> response) {
                Log.i("Response", response.toString());
            }

            @Override
            public void onFailure(Throwable t) {
                Log.i("Failure", t.toString());
            }
        });
        try{
            callPet.execute();
        } catch (IOException e){
            e.printStackTrace();
        }

    }
}

Mon interface qui est devenue mon API

public interface GitHubService {
    @GET("/ **sample here** /{petId}/{otherPet}")
    Call<Pet> getResponse(@Path("petId") String userId, @Path("otherPet") String otherPet);
}

Et enfin la classe Pet qui devrait être la réponse:

public class Pet implements Parcelable {

    public static final String ACTIVE = "1";
    public static final String NOT_ACTIVE = "0";

    @SerializedName("is_active")
    @Expose
    private String isActive;
    @SerializedName("pet_id")
    @Expose
    private String petId;
    @Expose
    private String name;
    @Expose
    private String gender;
    @Expose
    private String age;
    @Expose
    private String breed;
    @SerializedName("profile_picture")
    @Expose
    private String profilePicture;
    @SerializedName("confirmation_status")
    @Expose
    private String confirmationStatus;

    /**
     *
     * @return
     * The confirmationStatus
     */
    public String getConfirmationStatus() {
        return confirmationStatus;
    }

    /**
     *
     * @param confirmationStatus
     * The confirmation_status
     */
    public void setConfirmationStatus(String confirmationStatus) {
        this.confirmationStatus = confirmationStatus;
    }

    /**
     *
     * @return
     * The isActive
     */
    public String getIsActive() {
        return isActive;
    }

    /**
     *
     * @param isActive
     * The is_active
     */
    public void setIsActive(String isActive) {
        this.isActive = isActive;
    }

    /**
     *
     * @return
     * The petId
     */
    public String getPetId() {
        return petId;
    }

    /**
     *
     * @param petId
     * The pet_id
     */
    public void setPetId(String petId) {
        this.petId = petId;
    }

    /**
     *
     * @return
     * The name
     */
    public String getName() {
        return name;
    }

    /**
     *
     * @param name
     * The name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     *
     * @return
     * The gender
     */
    public String getGender() {
        return gender;
    }

    /**
     *
     * @param gender
     * The gender
     */
    public void setGender(String gender) {
        this.gender = gender;
    }

    /**
     *
     * @return
     * The age
     */
    public String getAge() {
        return age;
    }

    /**
     *
     * @param age
     * The age
     */
    public void setAge(String age) {
        this.age = age;
    }

    /**
     *
     * @return
     * The breed
     */
    public String getBreed() {
        return breed;
    }

    /**
     *
     * @param breed
     * The breed
     */
    public void setBreed(String breed) {
        this.breed = breed;
    }

    /**
     *
     * @return
     * The profilePicture
     */
    public String getProfilePicture() {
        return profilePicture;
    }

    /**
     *
     * @param profilePicture
     * The profile_picture
     */
    public void setProfilePicture(String profilePicture) {
        this.profilePicture = profilePicture;
    }


    protected Pet(Parcel in) {
        isActive = in.readString();
        petId = in.readString();
        name = in.readString();
        gender = in.readString();
        age = in.readString();
        breed = in.readString();
        profilePicture = in.readString();
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(isActive);
        dest.writeString(petId);
        dest.writeString(name);
        dest.writeString(gender);
        dest.writeString(age);
        dest.writeString(breed);
        dest.writeString(profilePicture);
    }

    @SuppressWarnings("unused")
    public static final Parcelable.Creator<Pet> CREATOR = new Parcelable.Creator<Pet>() {
        @Override
        public Pet createFromParcel(Parcel in) {
            return new Pet(in);
        }

        @Override
        public Pet[] newArray(int size) {
            return new Pet[size];
        }
    };
}
Earwin delos Santos
la source
veuillez ajouter la chaîne de réponse de ce lien mysample.com/development/cuteness
koutuk
@koutuk c'est juste un échantillon, btw j'ai déjà changé mon message
Earwin delos Santos
à quelle ligne vous obtenez une erreur ....
koutuk
vous devriez passer par youtube.com/watch?v=gGuUBlzmtPQ cette vidéo
koutuk
ohh c'est l'ancien. essayez de visiter retrofit square.github.io/retrofit
Earwin delos Santos

Réponses:

217

Avant 2.0.0, le convertisseur par défaut était un convertisseur gson, mais dans 2.0.0et plus tard, le convertisseur par défaut est ResponseBody. À partir de la documentation:

Par défaut, Retrofit ne peut désérialiser les corps HTTP que dans le ResponseBodytype d'OkHttp et il ne peut accepter que son RequestBodytype pour @Body.

Dans 2.0.0+, vous devez spécifier explicitement que vous voulez un convertisseur Gson:

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("**sample base url here**")
    .addConverterFactory(GsonConverterFactory.create())
    .build();

Vous devrez également ajouter la dépendance suivante à votre fichier gradle:

compile 'com.squareup.retrofit2:converter-gson:2.1.0'

Utilisez la même version pour le convertisseur que pour votre rénovation. Ce qui précède correspond à cette dépendance de mise à niveau:

compile ('com.squareup.retrofit2:retrofit:2.1.0')

Notez également qu'au moment de la rédaction de cet article, les documents de mise à jour ne sont pas complètement mis à jour, c'est pourquoi cet exemple vous a causé des problèmes. À partir de la documentation:

Remarque: ce site est toujours en cours d'extension pour les nouvelles API 2.0.

iagreen
la source
Je rencontre toujours le problème
user3475052
217

Si quelqu'un rencontre jamais cela à l'avenir parce que vous essayez de définir votre propre usine de convertisseur personnalisé et que vous obtenez cette erreur, cela peut également être causé par le fait d'avoir plusieurs variables dans une classe avec un nom mal orthographié ou le même nom sérialisé. C'EST À DIRE:

public class foo {
  @SerializedName("name")
  String firstName;
  @SerializedName("name")
  String lastName;
}

Avoir des noms sérialisés définis deux fois (probablement par erreur) générera également exactement la même erreur.

Mise à jour : gardez à l'esprit que cette logique est également vraie via l'héritage. Si vous étendez à une classe parent avec un objet qui a le même nom sérialisé que vous le faites dans la sous-classe, cela provoquera le même problème.

PGMacDesign
la source
2
C'était le problème pour moi, j'ai oublié de supprimer un champ à l'intérieur d'une classe enfant que j'ai déplacée vers la classe parent. Merci mec!
Vucko le
1
Merci de m'avoir sauvé de 2 jours de luttes. J'ai fait la même erreur en déclarant 2 variables avec les mêmes noms sérialisés.
Valynk le
9

Sur la base des meilleurs commentaires, j'ai mis à jour mes importations

implementation 'com.squareup.retrofit2:retrofit:2.1.0'
implementation 'com.squareup.retrofit2:converter-gson:2.1.0'

J'ai utilisé http://www.jsonschema2pojo.org/ afin de créer des pojo à partir des résultats Spotify json et en veillant à spécifier le format Gson.

De nos jours, il existe des plugins Android Studio qui peuvent créer les modèles de données pojo ou Kotlin pour vous. Quicktype est une excellente option pour mac. https://itunes.apple.com/us/app/paste-json-as-code-quicktype/id1330801220

Juan Mendez
la source
6

assurez-vous simplement que vous n'utilisez pas deux fois le même nom de sérialisation

 @SerializedName("name") val name: String
 @SerializedName("name") val firstName: String

enlève juste un d'entre eux

Mohamed Farahat
la source
Merci, vous avez sauvé ma journée :)
Hemendra Gangwar
c'était mon problème .. Merci mon frère ...
happy_Coding il y a
4

Dans mon cas, j'avais un objet TextView dans ma classe modale et GSON ne savait pas comment le sérialiser. Le marquer comme «transitoire» a résolu le problème.

Saksham Dhawan
la source
Bien que cela le rende visible, gardez à l'esprit que cela ne fonctionnera pas si vous obscurcissez le code (IE, via proguard) et le publiez; mieux vaut avoir les annotations SerializedName ou Exposed à la place
PGMacDesign
3

Le post de @ Silmarilos m'a aidé à résoudre ce problème. Dans mon cas, c'est que j'ai utilisé "id" comme nom sérialisé, comme ceci:

 @SerializedName("id")
var node_id: String? = null

et je l'ai changé en

 @SerializedName("node_id")
var node_id: String? = null

Tout fonctionne maintenant. J'ai oublié que «id» est un attribut par défaut.

Glenncito
la source
1

Cela peut aider quelqu'un

Dans mon cas, j'ai écrit par erreur SerializedName comme ceci

@SerializedName("name","time")
String name,time; 

Ça devrait être

@SerializedName("name")
String name;

@SerializedName("time")
String time;
RAJESH KUMAR ARUMUGAM
la source
0

Hé, je traversais le même problème aujourd'hui m'a pris une journée entière pour trouver une solution, mais c'est la solution que j'ai finalement trouvée. J'utilise Dagger dans mon code et j'avais besoin d'implémenter le convertisseur Gson dans mon instance de mise à niveau.

donc c'était mon code avant

@Provides
    @Singleton
    Retrofit providesRetrofit(Application application,OkHttpClient client) {
        String SERVER_URL=URL;
        Retrofit.Builder builder = new Retrofit.Builder();
        builder.baseUrl(SERVER_URL);
        return builder
                .client(client)
                .build();
    }

c'est ce que j'ai fini avec

@Provides
    @Singleton
    Retrofit providesRetrofit(Application application,OkHttpClient client, Gson gson) {
        String SERVER_URL=URL;
        Retrofit.Builder builder = new Retrofit.Builder();
        builder.baseUrl(SERVER_URL);
        return builder
                .client(client)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .build();
    }

remarquez qu'il n'y a pas de convertisseur dans le premier exemple et l'ajout si vous n'avez pas instancié Gson, vous l'ajoutez comme ceci

    @Provides
    @Singleton
    Gson provideGson() {
        GsonBuilder gsonBuilder = new GsonBuilder();

   gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);
        return gsonBuilder.create();
    }

et assurez-vous de l'avoir inclus dans l'appel de méthode pour la modernisation.

espère encore une fois que cela aide quelqu'un comme moi.

écureuil
la source
0

Dans mon cas, c'était dû à essayer de prendre une liste retournée par mon service dans une ArrayList. Donc ce que j'avais était:

@Json(name = "items")
private ArrayList<ItemModel> items;

quand j'aurais dû avoir

@Json(name = "items")
private List<ItemModel> items;

J'espère que cela aide quelqu'un!

Riot va Woof
la source
0

Dans mon cas, le problème était que mon modèle SUPERCLASS avait ce champ défini. Très stupide, je sais ...

SkyNet801
la source