Earwin delos Santos Earwin delos Santos - 6 months ago 28
Android Question

Unable to create converter for my class in Android Retrofit library

Im migrating from using Volley to Retrofit, I already have gson class that I used before for converting JSONObject reponse to a object that implements gson annotations. When I'm trying to make http get request using retrofit but then my app crashes with this 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


Im following the guide in retrofit site and I come up with these implementations :

This is my activity where I am trying to execute the retro http request:

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

}
}


My interface which turned to be my API

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


And finally the Pet class which should be the reponse:

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];
}
};
}

Answer

Prior to 2.0.0, the default converter was a gson converter, but in 2.0.0, the default converter is ResponseBody. From the docs --

By default, Retrofit can only deserialize HTTP bodies into OkHttp's ResponseBody type and it can only accept its RequestBody type for @Body.

In 2.0.0, you need to explicitly specify you want a Gson converter --

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

You will also need to add the following dependency to your gradle file --

compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta3'

Also, note as of writing this, the retrofit docs are not completely updated, which is why that example got you into trouble. From the docs --

Note: This site is still in the process of being expanded for the new 2.0 APIs.

Update: For later releases, remember to keep the version of the gson converter lib the same as the retrofit version. For example, for the _beta3 release, make sure you use

compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta3`