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
retrofit siteのガイドに従っていると、これらの実装を思いつきます。
これはレトロな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];
}
};
}
2.0.0
より前は、デフォルトのコンバーターはgsonコンバーターでしたが、2.0.0
以降では、デフォルトのコンバーターはResponseBody
です。ドキュメントから:
デフォルトでは、RetrofitはHTTPボディをOkHttpの
ResponseBody
型にのみデシリアライズでき、@Body
のRequestBody
型のみを受け入れます。
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向けに拡張中です。
独自のカスタムコンバータファクトリを定義しようとしてこのエラーが発生しているため、将来これに遭遇した人は、同じシリアル化された名前のクラスに複数の変数があることも原因となる可能性があります。 IE:
public class foo {
@SerializedName("name")
String firstName;
@SerializedName("name")
String lastName;
}
シリアル化された名前を2回定義すると(おそらく誤って)、これとまったく同じエラーがスローされます。
更新:このロジックは継承を介しても成り立つことに注意してください。サブクラスで行うのと同じSerialized nameを持つオブジェクトを持つ親クラスに拡張する場合、この同じ問題が発生します。
一番上のコメントに基づいて、インポートを更新しました
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形式を指定するようにしました。
最近では、pojoまたはKotlinデータモデルを作成できるAndroid Studioプラグインがあります。 Macの優れたオプションの1つはQuicktypeです。 https://iTunes.Apple.com/us/app/paste-json-as-code-quicktype/id133080122
私の場合、モーダルクラス内にTextViewオブジェクトがあり、GSONはそれをシリアル化する方法を知りませんでした。 「一時的」としてマークすることで問題は解決しました。
@Silmarilosの投稿は、これを解決するのに役立ちました。私の場合、次のように、シリアル化された名前として「id」を使用していました。
@SerializedName("id")
var node_id: String? = null
に変更しました
@SerializedName("node_id")
var node_id: String? = null
すべてが動作しています。 「id」がデフォルトの属性であることを忘れていました。
これは誰かを助けるかもしれない
私の場合、誤って SerializedName のように書きました
@SerializedName("name","time")
String name,time;
そのはず
@SerializedName("name")
String name;
@SerializedName("time")
String time;
私の場合、サービスから返されたリストをArrayListに取り込もうとしたためです。だから私が持っていたのは:
@Json(name = "items")
private ArrayList<ItemModel> items;
すべきだったとき
@Json(name = "items")
private List<ItemModel> items;
これが誰かを助けることを願っています!
ちょっと私は今日同じ問題を経験していましたが、解決策を見つけるために丸一日かかりましたが、これは最終的に見つけた解決策です。私のコードで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();
}
そして、改良のためのメソッド呼び出しにそれが含まれていることを確認してください。
これが私のような人の助けになることをもう一度願っています。