Retrofit2 Android: retrieve nested data (current error: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $)
Retrofit2 Android: retrieve nested data (current error: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $)
我正在尝试从 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 中获取一些数据只是一个数组(没有嵌套)。我怎么能让这个工作?目前我在 activity:
中得到了这段代码
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 接口正在 activity:
中使用
public interface MarvelAPI {
@GET("characters")
Call<List<Character>> getCharacters();
}
这显然不起作用,因为它给了我一个“Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $”的错误。我还尝试制作 2 个新的 类:CharacterData,它有一个结果列表,还有 CharactersResults,它有一个字符列表,但这也不起作用(即使在尝试更改 call.enqueue 和 MarvelAPI 界面之后)。或者我真的不知道如何更改我的 call.enqueue 让它使用这 3 个 类 获取正确的数据。谁能给我指出正确的方向?
(PS: 我知道将所有结果放入文本视图会很麻烦,但这只是使 API 检索正确数据的第一个版本,我确实计划将其放入网格或其他东西)
处理此问题的最简单方法实际上是使用您提到的模型。本质上,使 java 对象模仿 json 结构。在这种情况下,您可以执行以下操作:
class CharacterData {
@SerializedName("results")
List<Character> characters;
// ...
}
class CharactersResults {
@SerializedName("data")
CharacterData data;
// ...
}
就像你说的,现在你需要改变改装电话。代理接口现在必须 return 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
我正在尝试从 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 中获取一些数据只是一个数组(没有嵌套)。我怎么能让这个工作?目前我在 activity:
中得到了这段代码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 接口正在 activity:
中使用public interface MarvelAPI {
@GET("characters")
Call<List<Character>> getCharacters();
}
这显然不起作用,因为它给了我一个“Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $”的错误。我还尝试制作 2 个新的 类:CharacterData,它有一个结果列表,还有 CharactersResults,它有一个字符列表,但这也不起作用(即使在尝试更改 call.enqueue 和 MarvelAPI 界面之后)。或者我真的不知道如何更改我的 call.enqueue 让它使用这 3 个 类 获取正确的数据。谁能给我指出正确的方向?
(PS: 我知道将所有结果放入文本视图会很麻烦,但这只是使 API 检索正确数据的第一个版本,我确实计划将其放入网格或其他东西)
处理此问题的最简单方法实际上是使用您提到的模型。本质上,使 java 对象模仿 json 结构。在这种情况下,您可以执行以下操作:
class CharacterData {
@SerializedName("results")
List<Character> characters;
// ...
}
class CharactersResults {
@SerializedName("data")
CharacterData data;
// ...
}
就像你说的,现在你需要改变改装电话。代理接口现在必须 return 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