web-dev-qa-db-fra.com

Retrofit2 Android: BEGIN_ARRAY attendu mais BEGIN_OBJECT à la ligne 1 colonne 2 chemin $

Je sais que ce n’est pas la première fois que quelqu'un pose la question de ce problème, mais avec Retrofit2, je ne trouve pas la bonne solution à mon problème. J'ai suivi un tutoriel en ligne et cela a bien fonctionné. Lorsque j'applique le même code à mon propre terminal, j'obtiens cette exception: Java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $ Je ne sais pas comment résoudre ce problème.

Interface:

public interface MyApiService {

// Is this right place to add these headers?
@Headers({"application-id: MY-APPLICATION-ID",
        "secret-key: MY-SECRET-KEY",
        "application-type: REST"})
@GET("Music")
Call<List<Music>> getMusicList();



Retrofit retrofit = new Retrofit.Builder()
        .baseUrl(MySettings.REST_END_POINT)
        .addConverterFactory(GsonConverterFactory.create())
        .build();
}

Code client:

MyApiService service = MyApiService.retrofit.create(MyApiService.class);
Call<List<Music>> call = service.getMusicList();
call.enqueue(new Callback<List<Music>>() {

    @Override
    public void onResponse(Call<List<Music>> call, Response<List<Music>> response) {
        Log.e("MainActivity", response.body().
    }

    @Override
    public void onFailure(Call<List<Music>> call, Throwable t) {
        Log.e("MainActivity", t.toString());
    }
});

Ce code fonctionne avec cette charge utile:

[
{
    "login": "JakeWharton",
    "id": 66577,
    "avatar_url": "https://avatars.githubusercontent.com/u/66577?v=3",
    "gravatar_id": "",
    "url": "https://api.github.com/users/JakeWharton",
    "html_url": "https://github.com/JakeWharton",
    "followers_url": "https://api.github.com/users/JakeWharton/followers",
    "following_url": "https://api.github.com/users/JakeWharton/following{/other_user}",
    "gists_url": "https://api.github.com/users/JakeWharton/gists{/Gist_id}",
    "starred_url": "https://api.github.com/users/JakeWharton/starred{/owner}{/repo}",
    "subscriptions_url": "https://api.github.com/users/JakeWharton/subscriptions",
    "organizations_url": "https://api.github.com/users/JakeWharton/orgs",
    "repos_url": "https://api.github.com/users/JakeWharton/repos",
    "events_url": "https://api.github.com/users/JakeWharton/events{/privacy}",
    "received_events_url": "https://api.github.com/users/JakeWharton/received_events",
    "type": "User",
    "site_admin": false,
    "contributions": 741
},
{....

mais pas avec celui-ci:

{
"offset": 0,
"data": [
    {
        "filename": "E743_1458662837071.mp3",
        "created": 1458662854000,
        "publicUrl": "https://api.backendless.com/dbb77803-1ab8-b994-ffd8-65470fa62b00/v1/files/music/E743_1458662837071.mp3",
        "___class": "Music",
        "description": "",
        "likeCount": 0,
        "title": "hej Susanne. ",
        "ownerId": "E743756F-E114-6892-FFE9-BCC8C072E800",
        "updated": null,
        "objectId": "DDD8CB3D-ED66-0D6F-FFA5-B14543ABC800",
        "__meta": "{\"relationRemovalIds\":{},\"selectedProperties\":[\"filename\",\"created\",\"publicUrl\",\"___class\",\"description\",\"likeCount\",\"title\",\"ownerId\",\"updated\",\"objectId\"],\"relatedObjects\":{}}"
    },
    {...

Mon cours de musique:

public class Music {

   private String ownerId;
   private String filename;
   private String title;
   private String description;
   private String publicUrl;
   private int likeCount;

   // Getters & Setters

}
47
oxyt

Lorsque vous dites "Ce code fonctionne avec cette charge utile: ... mais pas avec celui-ci: ...", c'est ce qui est attendu et c'est ainsi que cela est supposé fonctionner. En fait, le message d'erreur vous indique que, lors de la conversion du json en un objet Java, l'appel attend un tableau dans le json mais un objet à la place.

Cet appel:

@GET("Music")
Call<List<Music>> getMusicList();

attend une liste d'objets Music, c'est pourquoi il fonctionne avec le json:

[
  {
    "login": "JakeWharton",
    ...
  },
  ...
]

Parce que le json lui-même est un tableau de vos objets Music (Retrofit peut convertir des tableaux json en Java). Pour le second json, vous avez juste un objet et non un tableau (remarquez le manque de [...]). Pour cela, vous devez créer un autre appel avec un autre modèle qui correspond à ce json. Supposons que vous ayez nommé le modèle MusicList. Voici à quoi pourrait ressembler l'appel:

@GET("Music")
Call<MusicList> getMusicList();

(Notez que vous devrez peut-être modifier le nom de la méthode si vous souhaitez conserver le premier appel et celui-ci).

Le modèle MusicList peut ressembler à ceci:

public class MusicList {
  @SerializedName("data")
  private List<Music> musics;
  // ...
}

Je suppose que le tableau data est une liste d'objets Music, mais j'ai remarqué que les jsons sont complètement différentes. Vous aurez peut-être besoin d'adapter cela aussi, mais je pense que vous obtenez l'image ici.

90
Fred

Je rencontre ce problème. Parce que playload est un objet plutôt qu'un tableau d'objets. Alors je supprime la liste.

Exemple de code

UserAPI.Java

public interface UserAPI {
    @GET("login/cellphone")
    Call<LoginResponse> login(@Query("phone") String phone, 
                              @Query("password") String password);
}

Code d'appel

Retrofit retrofit = new Retrofit
        .Builder()
        .addConverterFactory(GsonConverterFactory.create())
        .baseUrl(Constant.CLOUD_MUSIC_API_BASE_URL)
        .build();

UserAPI userAPI = retrofit.create(UserAPI.class);

userAPI.login(phone, password).enqueue(new Callback<LoginResponse>() {
    @Override
    public void onResponse(Call<LoginResponse> call, Response<LoginResponse> response) {
        System.out.println("onResponse");
        System.out.println(response.body().toString());
    }

    @Override
    public void onFailure(Call<LoginResponse> call, Throwable t) {
        System.out.println("onFailure");
        System.out.println(t.fillInStackTrace());
    }
});
2
shellhub