web-dev-qa-db-fra.com

Impossible de créer un convertisseur pour ma classe dans Android Bibliothèque de reconversion

En migrant de Volley à Retrofit, j’ai déjà utilisé la classe gson que j’avais utilisée auparavant pour convertir la réponse JSONObject en un objet implémentant des annotations gson. Lorsque j'essaie de créer une requête HTTP avec retrofit, mon application se bloque alors avec l'erreur suivante:

 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 dans retrofit site et je propose ces implémentations:

Voici mon activité pour laquelle j'essaie 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 s'est avérée être 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];
        }
    };
}
112

Avant 2.0.0, le convertisseur par défaut était un convertisseur gson, mais dans 2.0.0 et plus tard, le convertisseur par défaut est ResponseBody. De la docs:

Par défaut, Retrofit peut uniquement désérialiser les corps HTTP dans le type ResponseBody d'OkHttp et n'accepter que son type RequestBody 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 adaptation. Ce qui précède correspond à cette dépendance de modernisation:

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

De plus, notez qu'au moment de l'écriture, les documents de mise à niveau ne sont pas complètement mis à jour, c'est pourquoi cet exemple vous a posé problème. De la docs:

Remarque: Ce site est toujours en cours d’extension pour les nouvelles API 2.0.

194
iagreen

Si jamais quelqu'un rencontre cela à l'avenir parce que vous tentez de définir votre propre fabrique de convertisseurs personnalisée et obtenez cette erreur, cela peut également être causé par le fait que plusieurs variables d'une classe portent le même nom sérialisé. C'EST À DIRE:

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

Ayant des noms sérialisés définis deux fois (probablement par erreur), cette même erreur sera également renvoyée.

Mise à jour: Gardez à l'esprit que cette logique est également vraie via l'héritage. Si vous étendez à une classe parente avec un objet qui porte le même nom sérialisé que celui de la sous-classe, le même problème se produira.

148
Silmarilos

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 pojos à partir des résultats Spotify json et en veillant à spécifier le format Gson.

De nos jours, Android Studio plugins permettent de créer pour vous les modèles de données pojo ou Kotlin. Quicktype est une excellente option pour mac. https://iTunes.Apple.com/us/app/paste-json-as-code-quicktype/id133080122

8
Juan Mendez

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.

3
Saksham Dhawan

Le message 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é pour

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

Tous travaillent maintenant. J'ai oublié que "id" est un attribut par défaut.

2
Glenncito

Cela peut aider quelqu'un

Dans mon cas, j'ai écrit à tort SerializedName comme ceci

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

CA devrait etre

@SerializedName("name")
String name;

@SerializedName("time")
String time;
1

Dans mon cas, il s’agissait d’essayer de prendre une liste renvoyée par mon service dans une liste de tableaux. 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 ça aide quelqu'un!

0
Riot Goes Woof

Hé, je passais par le même problème aujourd'hui, il m'a fallu 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 exemple 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 comme il n'y a pas de convertisseur dans le premier exemple et l'addition 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 que vous l'avez inclus dans l'appel de méthode pour la mise à niveau.

encore une fois, espérons que cela aidera quelqu'un comme moi.

0
squirrel