it-swarm.com.de

Retrofit2 Android: BEGIN_ARRAY erwartet, aber BEGIN_OBJECT in Zeile 1, Spalte 2, Pfad $

Ich weiß, dass dies nicht das erste Mal ist, dass jemand nach diesem Problem fragt, aber mit Retrofit2 kann ich nicht die richtige Lösung für mein Problem finden. Ich bin einem Online-Tutorial gefolgt und es hat gut funktioniert. Wenn ich denselben Code auf meinen eigenen Endpunkt angewendet habe, erhalte ich diese Ausnahme: Java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $ Ich weiß nicht, wie ich das lösen soll.

Schnittstelle:

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

Kundencode:

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

Dieser Code arbeitet mit dieser Nutzlast:

[
{
    "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
},
{....

aber nicht mit diesem:

{
"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\":{}}"
    },
    {...

Meine Musikklasse:

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

Wenn Sie sagen "Dieser Code funktioniert mit dieser Nutzlast: ... aber nicht mit dieser: ...", wird das erwartet und so soll es funktionieren. Tatsächlich sagt Ihnen die Fehlermeldung, dass der Aufruf beim Konvertieren des json in ein Java object ein Array im json erwartete, aber stattdessen ein Objekt bekam.

Dieser Anruf:

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

erwartet eine Liste von Music Objekten, deshalb funktioniert es mit dem json:

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

Da der json selbst ein Array Ihrer Music -Objekte ist (Retrofit kann zwischen json-Arrays in Java listen) konvertieren. Für den zweiten json haben Sie nur ein Objekt und kein Array (Beachten Sie das Fehlen von [...]). Dazu müssen Sie einen weiteren Aufruf mit einem anderen Modell erstellen, das diesem JSON zugeordnet ist. Nehmen wir an, Sie haben das Modell MusicList genannt. So könnte der Anruf aussehen:

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

(Beachten Sie, dass Sie möglicherweise den Methodennamen ändern müssen, wenn Sie sowohl den ersten als auch diesen Aufruf beibehalten möchten.).

Das MusicList Modell kann ungefähr so ​​aussehen:

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

Ich gehe davon aus, dass das Array data eine Liste von Music Objekten ist, aber ich habe bemerkt, dass die JSONs völlig unterschiedlich sind. Möglicherweise müssen Sie dies auch anpassen, aber ich denke, Sie bekommen das Bild hier.

90
Fred

Ich treffe auf dieses Problem. Weil Playload ein Objekt anstelle eines Objektarrays ist. Also entferne ich List.

Code-Beispiel

UserAPI.Java

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

Code anrufen

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