Невозможно создать конвертер для моего класса в библиотеке Android Retrofit

131

Я перехожу с использования Volley на Retrofit, у меня уже есть класс gson, который я использовал раньше для преобразования ответа JSONObject в объект, реализующий аннотации gson. Когда я пытаюсь сделать HTTP-запрос на получение с помощью модернизации, но затем мое приложение вылетает с этой ошибкой:

 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

Я следую руководству на сайте модернизации, и я придумал следующие реализации:

Это моя деятельность, когда я пытаюсь выполнить ретро-запрос http:

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

    }
}

Мой интерфейс, который стал моим API

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

И, наконец, класс Pet, который должен быть ответом:

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];
        }
    };
}
Эрвин делос Сантос
источник
пожалуйста, добавьте строку ответа этой ссылки mysample.com/development/cuteness
koutuk
@koutuk, это всего лишь образец, кстати, я уже изменил свой пост
Earwin delos Santos
в какой строке вы получаете ошибку ....
koutuk 03
Вам следует просмотреть youtube.com/watch?v=gGuUBlzmtPQ это видео
koutuk
ох, это старый. попробуйте посетить retrofit square.github.io/retrofit
Earwin delos Santos

Ответы:

217

До 2.0.0, конвертер по умолчанию был gson конвертер, но 2.0.0и позже конвертер по умолчанию ResponseBody. Из документов:

По умолчанию Retrofit может десериализовать HTTP-тела только в ResponseBodyтип OkHttp и может принимать только его RequestBodyтип для @Body.

В 2.0.0+вам необходимо явно указать, что вы хотите конвертер Gson:

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

Вам также нужно будет добавить следующую зависимость в ваш файл gradle:

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

Используйте для преобразователя ту же версию, что и для модернизации. Приведенное выше соответствует этой зависимости от модернизации:

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

Также обратите внимание, что на момент написания этой статьи документы по модернизации не обновлены полностью, поэтому этот пример доставил вам проблемы. Из документов:

Примечание. Этот сайт все еще находится в процессе расширения для новых API 2.0.

iagreen
источник
у меня все еще проблема
user3475052
220

Если кто-нибудь когда-либо столкнется с этим в будущем, потому что вы пытаетесь определить свою собственную фабрику преобразователей и получаете эту ошибку, это также может быть вызвано наличием нескольких переменных в классе с ошибочным или тем же сериализованным именем. IE:

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

Если сериализованные имена определены дважды (вероятно, по ошибке), это также вызовет ту же ошибку.

Обновление : имейте в виду, что эта логика также верна через наследование. Если вы расширите до родительского класса с помощью объекта, который имеет то же сериализованное имя, что и в подклассе, это вызовет ту же проблему.

PGMacDesign
источник
2
Это была проблема для меня, я забыл удалить поле внутри дочернего класса, который я переместил в родительский класс. Спасибо чувак!
Vučko
1
Спасибо, что спас меня от двух дней борьбы. Я совершил ту же ошибку, объявив 2 переменные с одинаковыми сериализованными именами.
Valynk
9

На основании главного комментария я обновил импорт

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

Я использовал http://www.jsonschema2pojo.org/ , чтобы создать pojo из результатов Spotify json и не забудьте указать формат Gson.

В наши дни есть плагины Android Studio, которые могут создавать модели данных pojo или Kotlin за вас. Отличный вариант для Mac - Quicktype. https://itunes.apple.com/us/app/paste-json-as-code-quicktype/id1330801220

Хуан Мендес
источник
6

просто убедитесь, что вы не используете одно и то же имя сериализации дважды

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

просто удали один из них

Мохамед Фарахат
источник
Спасибо, вы спасли мне день :)
Хемендра Гангвар
это была моя проблема .. Спасибо, брат ...
happy_Coding
4

В моем случае у меня был объект TextView внутри моего модального класса, и GSON не знал, как его сериализовать. Пометка его как «временного» решила проблему.

Сакшам Дхаван
источник
Хотя это сделает его видимым, имейте в виду, что это не сработает, если вы запутаете код (IE, через proguard) и опубликуете его; лучше иметь аннотации SerializedName или Exposed
PGMacDesign
3

Сообщение @ Silmarilos помогло мне решить эту проблему. В моем случае это было то, что я использовал id как сериализованное имя, например:

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

и я изменил это на

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

Все работает сейчас. Я забыл, что id - это атрибут по умолчанию.

Glenncito
источник
1

Это может кому-то помочь

В моем случае я ошибочно написал SerializedName вот так

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

Так должно быть

@SerializedName("name")
String name;

@SerializedName("time")
String time;
РАДЖЕШ КУМАР АРУМУГАМ
источник
0

Привет, я столкнулся с той же проблемой, сегодня мне потребовался целый день, чтобы найти решение, но это решение, которое я наконец нашел. Я использую Dagger в своем коде, и мне нужно было реализовать конвертер Gson в моем модифицированном экземпляре.

так что это был мой код раньше

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

это было то, с чем я закончил

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

обратите внимание, что в первом примере нет конвертера, и если вы не создали экземпляр Gson, вы добавляете его следующим образом

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

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

и убедитесь, что вы включили его в вызов метода для модернизации.

еще раз надеюсь, что это поможет кому-то вроде меня.

белка
источник
0

В моем случае это произошло из-за попытки перенести список, возвращаемый моей службой, в ArrayList. Итак, что у меня было:

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

когда я должен был иметь

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

Надеюсь, это кому-то поможет!

Бунт идет гав
источник
0

В моем случае проблема заключалась в том, что в моей модели SUPERCLASS было определено это поле. Я знаю, очень глупо ...

SkyNet801
источник