ไม่สามารถสร้างตัวแปลงสำหรับชั้นเรียนของฉันในห้องสมุด Android Retrofit


130

ฉันย้ายจากการใช้ Volley เป็น Retrofit ฉันมีคลาส gson ที่ฉันใช้มาก่อนสำหรับการแปลง JSONObject reponse เป็นวัตถุที่ใช้การเพิ่มความคิดเห็น 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 ซึ่งน่าจะเป็น 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];
        }
    };
}

กรุณาเพิ่มการตอบสนองสตริงของลิงค์นี้mysample.com/development/cuteness
koutuk

@koutuk นั่นเป็นเพียงตัวอย่าง btw ฉันเปลี่ยนโพสต์ของฉันแล้ว
Earwin delos Santos

บรรทัดที่คุณจะได้รับข้อผิดพลาด ....
koutuk

คุณควรผ่านyoutube.com/watch?v=gGuUBlzmtPQวิดีโอนี้
koutuk

โอ้นั่นเป็นของเก่า ลองไปชม retrofit square.github.io/retrofit
Earwin delos Santos

คำตอบ:


217

ก่อนที่จะ2.0.0แปลงเริ่มต้นเป็นแปลง gson แต่ในและต่อมาแปลงเริ่มต้นคือ2.0.0 ResponseBodyจากเอกสาร:

โดยค่าเริ่มต้น Retrofit สามารถทำการ deserialize เนื้อความ 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'

ใช้เวอร์ชันเดียวกันสำหรับตัวแปลงเช่นเดียวกับชุดติดตั้งเพิ่มเติมของคุณ ด้านบนตรงกับการติดตั้งเพิ่มเติม retrofit นี้:

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

นอกจากนี้โปรดทราบว่าเมื่อมีการเขียนสิ่งนี้ชุดติดตั้งเพิ่มเติมยังไม่ได้รับการอัปเดตอย่างสมบูรณ์ซึ่งเป็นสาเหตุที่ตัวอย่างดังกล่าวทำให้คุณเดือดร้อน จากเอกสาร:

หมายเหตุ: ไซต์นี้ยังอยู่ในขั้นตอนการขยายสำหรับ API 2.0 ใหม่


ฉันยังคงมีปัญหา
user3475052

217

หากใครก็ตามที่เจอสิ่งนี้ในอนาคตเพราะคุณกำลังพยายามกำหนดตัวแปลงจากโรงงานของคุณเองและได้รับข้อผิดพลาดนี้ก็อาจเกิดจากการมีตัวแปรหลายตัวในคลาสที่มีชื่อที่สะกดผิดหรือชื่ออนุกรม IE:

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

การมีชื่อต่อเนื่องกันสองครั้ง (น่าจะผิด) จะทำให้เกิดข้อผิดพลาดเดียวกัน

อัปเดต : โปรดทราบว่าตรรกะนี้ถือเป็นจริงผ่านการสืบทอด ถ้าคุณขยายไปยังคลาสพาเรนต์ด้วยวัตถุที่มีชื่ออนุกรมเหมือนกันกับที่คุณทำในคลาสย่อยมันจะทำให้เกิดปัญหาเดียวกันนี้


2
นี่เป็นปัญหาสำหรับฉันลืมลบฟิลด์ในชั้นเรียนสำหรับเด็กที่ฉันย้ายไปที่ชั้นผู้ปกครอง ขอบคุณคน!
Vucko

1
ขอบคุณคุณช่วยฉันจากการต่อสู้ 2 วัน ฉันทำผิดพลาดโดยการประกาศตัวแปร 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

เพียงลบหนึ่งรายการ


ขอบคุณคุณช่วยชีวิตฉันไว้ :)
Hemendra Gangwar

มันเป็นปัญหาของฉัน .. ขอบคุณพี่ชายของคุณ ...
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' เป็นแอตทริบิวต์เริ่มต้น


1

นี่อาจช่วยใครซักคน

ในกรณีของฉันผิดฉันเขียนSerializedNameเช่นนี้

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

มันควรจะเป็น

@SerializedName("name")
String name;

@SerializedName("time")
String time;

0

เฮ้ฉันเจอปัญหาเดียวกันวันนี้พาฉันไปทั้งวันเพื่อหาทางแก้ปัญหา แต่นี่เป็นวิธีแก้ปัญหาที่ฉันค้นพบในที่สุด กำลังใช้กริชในรหัสของฉันและฉันจำเป็นต้องใช้ตัวแปลง 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 ของฉันมีฟิลด์นี้กำหนดไว้ โง่มากฉันรู้ ....

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.