无法在Android Retrofit库中为我的班级创建转换器


129

从使用Volley迁移到Retrofit的过程中,我已经有了之前用于将JSONObject响应转换为实现gson注释的对象的gson类。当我尝试使用改造使http get请求但我的应用程序崩溃时出现以下错误:

 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 2015年

@koutuk只是一个例子,顺便说一句,我已经更改了帖子
Earwin delos Santos 2015年

在哪一行出现错误....
koutuk

您应该通过youtube.com/watch?v=gGuUBlzmtPQ观看此视频
koutuk 2015年

哦,那是旧的。尝试访问改造Square.github.io/retrofit
Earwin delos Santos,

Answers:


217

在此之前2.0.0,默认转换器是gson转换器,但在2.0.0以后,默认转换器是ResponseBody。从文档:

默认情况下,Retrofit只能将HTTP正文反序列化为OkHttp的 ResponseBody类型,并且只能接受的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')

另外,在撰写本文时,请注意,改造文档尚未完全更新,这就是该示例使您陷入困境的原因。从文档:

注意:此站点仍在针对新的2.0 API进行扩展。


我仍然遇到问题
user3475052

215

如果将来有人试图定义自己的自定义转换器工厂而遇到此错误,那么也可能是由于类中的多个变量拼写错误或序列化名称相同而导致的。IE浏览器:

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

两次定义序列化名称(可能是错误地)也将引发完全相同的错误。

更新:请记住,此逻辑通过继承也成立。如果使用与您在子类中具有相同的序列化名称的对象扩展到父类,则将导致同样的问题。


2
这对我来说是个问题,忘记了删除移到父类的子类中的字段。谢啦!
Vucko

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/来从Spotify json结果创建pojo,并确保指定Gson格式。

如今,有一些Android Studio插件可以为您创建pojo或Kotlin数据模型。Mac的一个不错的选择是Quicktype。 https://itunes.apple.com/cn/app/paste-json-as-code-quicktype/id1330801220


4

就我而言,我的模态类中有一个TextView对象,GSON不知道如何序列化它。将其标记为“瞬态”即可解决该问题。


尽管这将使它可见,但是请记住,如果您混淆了代码(IE,通过proguard)并发布了代码,它将无法正常工作。最好有要么SerializedName或暴露的注解,而不是
PGMacDesign


3

@Silmarilos的帖子帮助我解决了这个问题。就我而言,是我使用“ id”作为序列化名称,如下所示:

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

然后我将其更改为

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

现在都在工作。我忘记了“ id”是默认属性。



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

就我而言,这是由于尝试将服务返回的List放入ArrayList中。所以我当时是:

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

当我应该有

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

希望这对某人有帮助!


0

就我而言,问题是我的SUPERCLASS模型在其中定义了此字段。非常愚蠢,我知道。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.