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

Unable to create converter for my class in Android Retrofit library

我正在从使用 Volley 迁移到 Retrofit,我已经有了 gson class,我之前使用它来将 JSONObject 响应转换为实现 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

我按照 retrofit 站点中的指南进行操作,并提出了这些实现:

这是我的 activity 我正在尝试执行复古 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);
}

最后是宠物 class,它应该是响应:

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];
        }
    };
}

2.0.0之前,默认转换器是gson转换器,但在2.0.0和之后的版本中,默认转换器是ResponseBody。来自文档:

By default, Retrofit can only deserialize HTTP bodies into OkHttp's ResponseBody type and it can only accept its RequestBody type for @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')

另外,请注意,在撰写本文时,改装文档尚未完全更新,这就是该示例给您带来麻烦的原因。来自文档:

Note: This site is still in the process of being expanded for the new 2.0 APIs.

根据热门评论我更新了导入

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/us/app/paste-json-as-code-quicktype/id1330801220

如果以后有人遇到这个问题,因为您正在尝试定义自己的自定义转换器工厂并收到此错误,这也可能是由于 class 中的多个变量拼写错误造成的或相同的序列化名称。即:

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

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

更新:请记住,这个逻辑也适用于继承。如果您使用与子 class 中具有相同序列化名称的对象扩展到父 class,则会导致同样的问题。

在我的例子中,我的模式 class 中有一个 TextView 对象,而 GSON 不知道如何序列化它。将其标记为 'transient' 解决了问题。

这可能对某人有帮助

在我的例子中,我错误地这样写了SerializedName

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

应该是

@SerializedName("name")
String name;

@SerializedName("time")
String time;

@Silmarilos 的 post 帮助我解决了这个问题。在我的例子中,我使用 "id" 作为序列化名称,如下所示:

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

我把它改成了

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

现在一切正常。我忘了 'id' 是默认属性。

嘿,我今天遇到同样的问题花了我一整天的时间来寻找解决方案,但这是我最终找到的解决方案。 我在我的代码中使用 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();
    }

并确保您已将其包含在改造方法调用中。

再次希望这对像我这样的人有所帮助。

在我的例子中,这是因为试图将我的服务返回的列表放入 ArrayList 中。所以我得到的是:

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

当我应该

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

希望这对某人有所帮助!

在我的例子中,问题是我的 SUPERCLASS 模型中定义了这个字段。很蠢,我知道....

只需确保您没有两次使用相同的序列化名称

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

只删除其中一个

build.gradle变化中

minifyEnabled true

minifyEnabled false

解决了我的问题。

就我而言,我将 MoshiRetrofit 一起使用,我的错误是:

我没有为包含在 Response class 服务中的对象定义 body

例如:

@JsonSerializable
data class Balance(
    @field:Json(name = "balance") var balance: Double,
    @field:Json(name = "currency") var currency: Currency

Currency class 是空的。所以我完成了它并解决了问题!

在我的例子中,我使用的是带有 Retrofit 2.0 的 Moshi 库,即

// Moshi
implementation 'com.squareup.moshi:moshi-kotlin:1.9.3'
// Retrofit with Moshi Converter
implementation 'com.squareup.retrofit2:converter-moshi:2.9.0'

我忘记将自定义 Moshi json 转换器适配器工厂对象传递给 moshi 转换器工厂构造函数。

private val moshi = Moshi.Builder() // adapter
    .add(KotlinJsonAdapterFactory())
    .build()

private val retrofit = Retrofit.Builder()
    .addConverterFactory(MoshiConverterFactory.create()) // <- missing moshi json adapter insance
    .baseUrl(BASE_URL)
    .build()

修复:.addConverterFactory(MoshiConverterFactory.create(moshi))

在我使用 kotlinx.serialization 的情况下,改造引发了相同的异常,

这是由于缺少 @Serializable 注释。

@Serializable
data class MyClass(
    val id: String
)