No se puede crear un convertidor para mi clase en la biblioteca de actualización de Android


Estoy migrando de usar Volley a Retrofit, ya tengo la clase gson que usé antes para convertir JSONObject reponse a un objeto que implementa anotaciones gson. Cuando estoy tratando de hacer una solicitud http get usando retrofit, pero luego mi aplicación se bloquea con este error:

 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

Estoy siguiendo la guía en el sitio retrofit y se me ocurren estas implementaciones:

Esta es mi actividad donde estoy tratando de ejecutar la petición http retro:

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

    }
}

Mi interfaz que se convirtió en mi API

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

Y finalmente la clase Pet que debería ser la respuesta:

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];
        }
    };
}
Author: Earwin delos Santos, 2015-09-03

6 answers

Antes de 2.0.0, el convertidor predeterminado era un convertidor gson, pero en 2.0.0 y más tarde el convertidor predeterminado es ResponseBody. De los documentos:

De forma predeterminada, el Retrofit solo puede deserializar los cuerpos HTTP en OkHttp ResponseBody tipo y solo puede aceptar su tipo RequestBody para @Body.

En 2.0.0+, debe especificar explícitamente que desea un convertidor Gson:

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

También necesitarás agregar la siguiente dependencia a tu archivo de gradle:

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

Uso la misma versión para el convertidor que lo hace para su retrofit. Lo anterior coincide con esta dependencia de retrofit:

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

También, tenga en cuenta que al escribir esto, los documentos de actualización no están completamente actualizados, por lo que ese ejemplo lo metió en problemas. De los documentos:

Nota: Este sitio todavía está en proceso de expansión para las nuevas API 2.0.

 171
Author: iagreen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-29 13:47:28

Si alguien se encuentra con esto en el futuro porque está tratando de definir su propia fábrica de convertidores personalizados y está obteniendo este error, también puede ser causado por tener múltiples variables en una clase con el mismo nombre serializado. IE:

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

Tener nombres serializados definidos dos veces (probablemente por error) también arrojará exactamente el mismo error.

Actualización : Tenga en cuenta que esta lógica también es válida a través de la herencia. Si se extiende a una clase padre con un objeto que tiene el mismo nombre serializado como lo hace en la sub-clase, causará este mismo problema.

 84
Author: Silmarilos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-11 20:43:16

Basado en el comentario principal actualizé mis importaciones

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

He usado http://www.jsonschema2pojo.org / con el fin de crear pojo de Spotify json resultados y asegurándose de especificar el formato Gson.

 6
Author: Juan Mendez,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-13 11:08:04

En mi caso, tenía un objeto TextView dentro de mi clase modal y GSON no sabía cómo serializarlo. Marcarlo como 'transitorio' resolvió el problema.

 3
Author: Saksham Dhawan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-18 13:54:06

Esto puede ayudar a alguien

En mi caso escribí erróneamente SerializedName así

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

Debe ser

@SerializedName("name")
String name;

@SerializedName("time")
String time;
 0
Author: RAJESH KUMAR ARUMUGAM,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-03 08:34:32

El post de@Silmarilos me ayudó a resolver esto. En mi caso, fue que usé "id" como un nombre serializado, así:

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

Y lo cambié a

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

Todos trabajando ahora. Olvidé que ' id ' es un atributo predeterminado.

 0
Author: Glenncito,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-10-05 14:06:05