Tidak dapat membuat konverter untuk kelas saya di pustaka Retrofit Android

130

Saya bermigrasi dari menggunakan Volley ke Retrofit, saya sudah memiliki kelas gson yang saya gunakan sebelumnya untuk mengubah respons JSONObject ke objek yang menerapkan penjelasan gson. Saat saya mencoba membuat http dapatkan permintaan menggunakan retrofit tapi kemudian aplikasi saya mogok dengan kesalahan ini:

 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

Saya mengikuti panduan di situs retrofit dan saya membuat implementasi ini:

Ini adalah aktivitas saya di mana saya mencoba mengeksekusi permintaan retro 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();
        }

    }
}

Antarmuka saya yang berubah menjadi API saya

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

Dan akhirnya kelas Pet yang seharusnya menjadi respons:

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];
        }
    };
}
Earwin delos Santos
sumber
silakan tambahkan String tanggapan dari tautan ini mysample.com/development/cuteness
koutuk
@koutuk itu hanya contoh, btw saya sudah mengubah posting saya
Earwin delos Santos
pada baris mana Anda mendapatkan kesalahan ....
koutuk
Anda harus melalui youtube.com/watch?v=gGuUBlzmtPQ video ini
koutuk
ohh itu yang lama. coba kunjungi retrofit square.github.io/retrofit
Earwin delos Santos

Jawaban:

217

Sebelum 2.0.0, konverter default adalah konverter gson, tetapi 2.0.0konverter default adalah dan kemudian ResponseBody. Dari dokumen:

Secara default, Retrofit hanya dapat menghilangkan bau badan HTTP menjadi tipe OkHttp ResponseBodydan hanya dapat menerima RequestBodytipenya @Body.

Di 2.0.0+, Anda perlu menentukan secara eksplisit bahwa Anda menginginkan konverter Gson:

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

Anda juga perlu menambahkan ketergantungan berikut ke file gradle Anda:

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

Gunakan versi yang sama untuk konverter seperti yang Anda lakukan untuk retrofit Anda. Yang di atas cocok dengan ketergantungan retrofit ini:

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

Juga, perhatikan saat menulis ini, dokumen retrofit tidak sepenuhnya diperbarui, itulah sebabnya contoh itu membuat Anda kesulitan. Dari dokumen:

Catatan: Situs ini masih dalam proses untuk diperluas untuk API 2.0 baru.

iagreen
sumber
saya masih mengalami masalah
user3475052
217

Jika ada yang pernah menemukan ini di masa depan karena Anda mencoba untuk mendefinisikan pabrik konverter kustom Anda sendiri dan mendapatkan kesalahan ini, itu juga dapat disebabkan oleh memiliki beberapa variabel di kelas dengan salah eja atau nama serial yang sama. YAITU:

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

Memiliki nama serial didefinisikan dua kali (kemungkinan karena kesalahan) juga akan membuang kesalahan yang sama persis ini.

Pembaruan : Ingatlah bahwa logika ini juga berlaku melalui pewarisan. Jika Anda memperluas ke kelas induk dengan objek yang memiliki nama seri yang sama seperti yang Anda lakukan di sub-kelas, itu akan menyebabkan masalah yang sama.

PGMacDesign
sumber
2
Ini masalah bagi saya, lupa menghapus bidang di dalam kelas anak yang saya pindah ke kelas induk. Terima kasih sobat!
Vucko
1
Terima kasih telah menyelamatkan saya dari 2 hari perjuangan. Saya membuat kesalahan yang sama dengan mendeklarasikan 2 variabel dengan nama serial yang sama.
Valynk
9

Berdasarkan komentar teratas saya memperbarui impor saya

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

Saya telah menggunakan http://www.jsonschema2pojo.org/ untuk membuat pojo dari hasil Spotify json dan memastikan untuk menentukan format Gson.

Saat ini ada plugin Android Studio yang dapat membuat model data pojo atau Kotlin untuk Anda. Salah satu opsi hebat untuk mac adalah Quicktype. https://itunes.apple.com/us/app/paste-json-as-code-quicktype/id1330801220

Juan Mendez
sumber
6

pastikan saja Anda tidak menggunakan nama cerita bersambung yang sama dua kali

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

hapus saja salah satunya

Mohamed Farahat
sumber
Terima kasih, kamu menyelamatkan hariku :)
Hemendra Gangwar
itu masalah saya .. Terima kasih teman Anda ...
happy_Coding
4

Dalam kasus saya, saya memiliki objek TextView di dalam kelas modal saya dan GSON tidak tahu cara membuat cerita bersambung. Menandainya sebagai 'sementara' menyelesaikan masalah.

Saksham Dhawan
sumber
Meskipun ini akan membuatnya terlihat, perlu diingat itu tidak akan berfungsi jika Anda mengaburkan kode (IE, melalui proguard) dan menerbitkannya; lebih baik memiliki anotasi SerializedName atau Ekspos sebagai gantinya
PGMacDesign
3

@ Posting Silmarilos membantu saya menyelesaikan ini. Dalam kasus saya, saya menggunakan "id" sebagai nama bersambung, seperti ini:

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

dan saya mengubahnya menjadi

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

Semua bekerja sekarang. Saya lupa bahwa 'id' adalah atribut default.

Glenncito
sumber
1

Ini dapat membantu seseorang

Dalam kasus saya keliru saya menulis SerializedName seperti ini

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

Harus

@SerializedName("name")
String name;

@SerializedName("time")
String time;
RAJESH KUMAR ARUMUGAM
sumber
0

Hei saya akan melalui masalah yang sama hari ini butuh saya sehari penuh untuk menemukan solusi tapi ini solusi yang saya temukan akhirnya. Saya menggunakan belati dalam kode saya dan saya perlu menerapkan konverter Gson dalam contoh retrofit saya.

jadi ini kode saya sebelumnya

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

inilah yang akhirnya saya lakukan

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

perhatikan bagaimana tidak ada konverter dalam contoh pertama dan tambahan jika Anda belum instantiated Gson Anda menambahkannya seperti ini

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

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

dan memastikan Anda telah memasukkannya dalam metode panggilan untuk retrofit.

sekali lagi berharap ini bisa membantu seseorang seperti saya.

tupai
sumber
0

Dalam kasus saya, itu karena mencoba mengambil Daftar yang dikembalikan oleh layanan saya ke ArrayList. Jadi yang saya miliki adalah:

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

padahal seharusnya aku punya

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

Semoga ini bisa membantu seseorang!

Kerusuhan Goes Woof
sumber
0

Dalam kasus saya, masalahnya adalah bahwa model SUPERCLASS saya menentukan bidang ini di dalamnya. Sangat bodoh, saya tahu ....

SkyNet801
sumber