Android Retrofitライブラリでクラスのコンバーターを作成できません


130

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

そして最後に、対応すべきペットクラス:

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

おお、それは古いものです。retrofit square.github.io/retrofit
Earwin delos Santos

回答:


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

216

独自のカスタムコンバーターファクトリを定義しようとしてこのエラーが発生しているために、今後誰かがこれに遭遇した場合、スペルが間違っているか、同じシリアル化された名前を持つクラスに複数の変数があることが原因である可能性もあります。IE:

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

シリアル化された名前を2回(誤って)定義した場合も、まったく同じエラーがスローされます。

更新:このロジックは継承によっても当てはまることに注意してください。サブクラスで行うのと同じシリアル化された名前を持つオブジェクトを持つ親クラスに拡張すると、この同じ問題が発生します。


2
これは私にとっての問題であり、親クラスに移動した子クラス内のフィールドを削除するのを忘れていました。ありがとう!
Vucko 2017

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形式を指定してくださいすることを作成するために。

最近では、pojoまたはKotlinデータモデルを作成できるAndroid Studioプラグインがあります。Macの優れたオプションの1つはQuicktypeです。 https://itunes.apple.com/us/app/paste-json-as-code-quicktype/id1330801220


5

同じシリアル化名を2回使用していないことを確認してください

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

それらの1つを削除するだけです


ありがとう、あなたは私の日を救った:)
Hemendra Gangwar

4

私の場合、モーダルクラス内にTextViewオブジェクトがあり、GSONはそれをシリアル化する方法を知りませんでした。「一時的」としてマークすることで問題は解決しました。


これによりコードが表示されますが、コードを難読化して(つまり、プロガードを介して)公開すると機能しないことに注意してください。代わりにSerializedNameまたはExposedアノテーションを使用することをお
勧めし

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

今日同じ問題を経験していると、解決策を見つけるのに丸一日かかりましたが、これが最終的に見つけた解決策です。私のコードで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モデルにこのフィールドが定義されていることでした。非常に愚かです、私は知っています...

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.