【问题标题】:How do I parse nested objects with Retrofit 2?如何使用 Retrofit 2 解析嵌套对象?
【发布时间】:2017-11-22 12:07:51
【问题描述】:

我正在使用一个newsapi,其 JSON 响应与此类似;

{
"status": "ok",
"articles": [
    {
        "source": {
            "id": "bbc-news",
            "name": "BBC News"
        },
        "author": "BBC News",
        "title": "Jubilation greets end of Mugabe era",
        "description": "Zimbabweans celebrate late into the night after Robert Mugabe resigns, ending 37-year rule.",
        "url": "http://www.bbc.co.uk/news/world-africa-42072673",
        "urlToImage": "https://ichef.bbci.co.uk/images/ic/1024x576/p05nt3bn.jpg",
        "publishedAt": "2017-11-22T02:46:09Z"
    },
    {
        "source": {
            "id": "bbc-news",
            "name": "BBC News"
        },
        "author": "BBC News",
        "title": "Dramatic moment N Korea soldier defects",
        "description": "He raced across the border on foot, closely pursued by North Korean troops who shot at him several times.",
        "url": "http://www.bbc.co.uk/news/world-asia-42075986",
        "urlToImage": "https://ichef.bbci.co.uk/news/1024/cpsprodpb/F519/production/_98854726_p05ntph4.jpg",
        "publishedAt": "2017-11-22T04:45:14Z"
    },
    {
      ....
    }
  ]
}

我正在尝试使用带有 GSON 的 Retrofit 2 来处理该响应。

我的 POJO 类是这些;

NewsList.java

public class NewsList {
  public Articles[] articles;
  private String status;

  @Override
  public String toString() {
    return "ClassPojo [articles = " + articles + ", status = " + status + "]";
  }

  // getters and setters
}

Articles.java

public class Articles {
  private String publishedAt;
  private String author;
  private String urlToImage;
  private String title;
  private Source source;
  private String description;
  private String url;

 // getters and setters
}

Source.java

public class Source {
  private String id;
  private String name;

  // getters and setters
}

我的改造客户端是这样的;

public interface NewsroomAPI {
  String BASE_URL = "https://newsapi.org/v2/";

  @GET("top-headlines")
  Call<NewsList> loadNews(@Query("sources") String source);

}

在我的MainActivity.java 中,我像这样调用改造客户端;

OkHttpClient okHttpClient = new OkHttpClient().newBuilder().addInterceptor(new Interceptor() {
    @Override public okhttp3.Response intercept(Chain chain) throws IOException {
        Request originalRequest = chain.request();
        Request.Builder builder = originalRequest.newBuilder().header("Authorization",
                getString(R.string.newsroom_api_key));
        Request newRequest = builder.build();
        return chain.proceed(newRequest);
    }
}).build();

Retrofit.Builder builder =
            new Retrofit.Builder()
                    .baseUrl(NewsroomAPI.BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create());

    Retrofit retrofit = builder.client(okHttpClient).build();
    NewsroomAPI getNewsAPI = retrofit.create(NewsroomAPI.class);

    Call<NewsList> call = getNewsAPI.loadNews("bbc-news");
    call.enqueue(new Callback<NewsList>() {
        @Override public void onResponse(Call<NewsList> call, Response<NewsList> response) {
            if (response.isSuccessful()) {
                NewsList newslist = response.body();
                Log.w(TAG, "Articles result: " + newslist);
            } else {
                Toast.makeText(getContext(), "Some error occurred while fetching results!",
                        Toast.LENGTH_SHORT).show();
            }
        }

        @Override public void onFailure(Call<NewsList> call, Throwable t) {
            Log.w(TAG, "Failed! ", t);
        }
    });

当我运行活动并记录结果时,问题就出现了。 我希望有一个带有status 和返回的articles 的日志。但是状态返回成功,但是articles对象是null。输出如下所示;

 W/GlobalNewsFragment: Articles result: ClassPojo [articles = null, status = ok]

问题似乎来自Retrofit2 反序列化返回的 JSON 对象的方式。是不是我做错了什么?

这些是我的 build.gradle 文件中的依赖项

compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
compile "com.android.support:recyclerview-v7:26.1.0"
compile "com.squareup.okhttp3:okhttp:3.8.0"

【问题讨论】:

  • 检查我更新的答案。

标签: java android gson retrofit2


【解决方案1】:

您的 POJO 类应如下所示。

public class Article {

@SerializedName("source")
@Expose
private Source source;
@SerializedName("author")
@Expose
private String author;
@SerializedName("title")
@Expose
private String title;
@SerializedName("description")
@Expose
private String description;
@SerializedName("url")
@Expose
private String url;
@SerializedName("urlToImage")
@Expose
private String urlToImage;
@SerializedName("publishedAt")
@Expose
private String publishedAt;
// your getter setter methods
}

您的NewsList POJO 如下所示。

public class NewsList {

@SerializedName("status")
@Expose
private String status;
@SerializedName("articles")
@Expose
private List<Article> articles = null;
// getter setter
}

还有你的source POJO,如下所示。

public class Source {

@SerializedName("id")
@Expose
private String id;
@SerializedName("name")
@Expose
private String name;
// getters setters 
}

【讨论】:

  • 我已经按照您的解决方案,但我仍然得到相同的结果; W/GlobalNewsFragment: Article result: ClassPojo [articles = null, status = ok]articles 对象还是空的。
  • 我认为如果你的NewsList pojo 是准确的,这是不可能的(检查articles 的getter setter 方法)。因为状态返回ok
  • 我的文章获取器和设置器; public List&lt;Article&gt; getArticles() { return articles; } public void setArticles(List&lt;Article&gt; articles) { this.articles = articles; }
  • 让我克隆你的仓库。
  • 感谢您的帮助。实际上问题出在我的 JSON 响应上,如果没有 HttpLoggingInterceptor,我无法直接记录。因此,我定义了 HttpLoggingInterceptor,将其添加到我的okHttpClient,然后我发现返回的文章位于sources 列表对象中,而不是articles 列表对象中。那是唯一的乏味。现在可以正常使用了。
【解决方案2】:

AFAIK Gson 将JsonArray 反序列化为List。试试这个:

public class NewsList {
  public List<Articles> articles;
  private String status;

  //some code
}

【讨论】:

    猜你喜欢
    • 2018-05-31
    • 2015-09-12
    • 2021-02-03
    • 2016-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-30
    • 2018-07-12
    相关资源
    最近更新 更多