Неможливо створити конвертер для мого класу в бібліотеці ретрофітів Android


130

Іммігруючи з використання 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

вам слід пройти через youtube.com/watch?v=gGuUBlzmtPQ це відео
koutuk

о, це стара. спробуйте відвідати модернізацію 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 API.


У мене все ще виникає проблема
користувач3475052

217

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

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

Якщо два рази визначені серіалізовані імена (швидше за все, помилково), це також призведе до такої самої помилки.

Оновлення : майте на увазі, що ця логіка також відповідає дійсності у спадок. Якщо ви поширитеся на батьківський клас із об'єктом, який має те саме серіалізоване ім’я, як і ви в підкласі, це спричинить ту саму проблему.


2
Це було проблемою для мене, я забув видалити поле всередині дочірнього класу, яке я перейшов до батьківського класу. Спасибі людино!
Вучко

1
Дякую, що ти врятував мене від двох днів боротьби. Я зробив ту саму помилку, оголосивши 2 змінні з однаковими серіалізованими іменами.
Валинк

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

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


Дякую, ти врятував мені день :)
Hemendra Gangwar

це було моєю проблемою .. Дякую
брату

4

У моєму випадку я мав об’єкт TextView всередині мого модального класу, і GSON не знав, як його серіалізувати. Позначивши це "тимчасовим", вирішив проблему.


Хоча це зробить це видимим, майте на увазі, що він не спрацює, якщо придушити код (IE, через proguard) та опублікувати його; краще мати замість цього SerializedName або Exposed анотації
PGMacDesign

3

@ Повідомлення Сілмарілоса допомогло мені вирішити це. У моєму випадку я полягав у тому, що я використовував "id" як серіалізоване ім'я, наприклад:

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

і я змінив його на

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

Усі працюють зараз. Я забув, що "id" - це атрибут за замовчуванням.


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 було визначено це поле. Дуже дурний, я знаю….

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.