首页 > 解决方案 > Retrofit2 Android:检索嵌套数据(当前错误:预期 BEGIN_ARRAY 但在第 1 行第 2 列路径 $ 处为 BEGIN_OBJECT)

问题描述

我正在尝试从Marvel API中检索一些字符数据,如下所示:

{
"code": 200,
"status": "Ok",
"copyright": "© 2019 MARVEL",
"attributionText": "Data provided by Marvel. © 2019 MARVEL",
"attributionHTML": "<a href=\"http://marvel.com\">Data provided by Marvel. © 2019 MARVEL</a>",
"etag": "cc6c6c3e7f5e336ecf899ab5652d55e6a3a51b09",
"data": 

{
    "offset": 0,
    "limit": 20,
    "total": 1493,
    "count": 20,
    "results": 

[
        {
        "id": 1011334,
        "name": "3-D Man",
        "description": "",
        "modified": "2014-04-29T14:18:17-0400",
        "thumbnail": {
        "path": "http://i.annihil.us/u/prod/marvel/i/mg/c/e0/535fecbbb9784",
        "extension": "jpg"
        },
        "resourceURI": "http://gateway.marvel.com/v1/public/characters/1011334",
        "comics": {},
        "series": {},
        "stories": {},
        "events": {},
        "urls": []
        },

但我显然只想显示结果(数据 -> 结果 -> 字符数组),我正在观看本教程,其中有人能够从一个简单的 API 获取一些数据,其中它只是一个数组(不是嵌套的)。我怎样才能使这项工作?目前我在我的活动中得到了这个代码:

textViewResult = findViewById(R.id.textView_result);

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://gateway.marvel.com/v1/public/")
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        MarvelAPI marvelAPI = retrofit.create(MarvelAPI.class);

        Call<List<Character>> call = marvelAPI.getCharacters();

        call.enqueue(new Callback<List<Character>>() {
            @Override
            public void onResponse(Call<List<Character>> call, Response<List<Character>> response) {
                if(!response.isSuccessful()){
                    textViewResult.setText("Code: " + response.code());
                    return;
                }
                List<Character> characters = response.body();

                for (Character character : characters){
                    String content = "";
                    content += "ID: " + character.getId() + "\n";
                    content += "Name: " + character.getName() + "\n";
                    content += "Description: " + character.getDescription() + "\n";
                    content += "Modified: " + character.getModified() + "\n";
                    content += "Thumbnail: " + character.getThumbnail() + "\n";
                    textViewResult.append(content);
                }
            }

            @Override
            public void onFailure(Call<List<Character>> call, Throwable t) {
                textViewResult.setText(t.getMessage());
            }
        });

活动中使用的 MarvelAPI 接口:

public interface MarvelAPI {

    @GET("characters")
    Call<List<Character>> getCharacters();

}

这显然不起作用,因为它给了我一个“预期的 BEGIN_ARRAY 但在第 1 行第 2 列路径 $ 的 BEGIN_OBJECT”错误。我还尝试创建 2 个新类:具有结果列表的CharacterData以及具有字符列表的 CharactersResults,但这也不起作用(即使在尝试更改 call.enqueue 和 MarvelAPI 接口之后)..或者我真的不知道如何更改我的 call.enqueue 以让它使用这 3 个类获取正确的数据。谁能指出我正确的方向?

(PS:我确实知道将所有结果放入 textview 很麻烦,但这只是让 API 检索正确数据的第一个版本,我确实计划将其放入网格或其他东西中)

标签: androidretrofit2

解决方案


处理此问题的最简单方法实际上是使用您提到的模型。本质上,使 java 对象模仿 json 结构。在这种情况下,您可以执行以下操作:

class CharacterData {
  @SerializedName("results")
  List<Character> characters;
  // ...
}

class CharactersResults {
  @SerializedName("data")
  CharacterData data;
  // ...
}

就像你说的,现在你需要改变改造电话。代理的接口现在必须返回CharactersResults

public interface MarvelAPI {
  @GET("characters")
  Call<CharactersResults> getCharacters();
}

这反过来也改变了回调参数:

call.enqueue(new Callback<CharactersResults>() {
   @Override
   public void onResponse(Call<CharactersResults> call, Response<CharactersResults> response) {
      // ...

      List<Character> characters = response.body().data.characters;

      // ...
   }

   @Override
   public void onFailure(Call<CharactersResults> call, Throwable t) {
      // ...
   }
});

PS:为简洁起见,我忽略了创建 getter 和 setter


推荐阅读