如何使用RestTemplate在Java中仅解析Web JSON的一部分?

时间:2019-08-29 08:50:52

标签: java json spring resttemplate

我正在尝试从以下API获取前5篇文章:https://newsapi.org/v2/top-headlines?sources=bbc-news&apiKey=19acc3a371d145ecb37a093f9985ea21

我的代码目前可以完美运行,但是它可以解析NewsAPI的所有10篇文章。

代码是:

public News parse() {

    return restTemplate.getForObject
                    ("https://newsapi.org/v2/top-headlines?sources=bbc-news&apiKey=19acc3a371d145ecb37a093f9985ea21", News.class);

    }
}

结果是:

{
    "totalResults": 10,
    "articles": [
        {
            "source": {
                "id": "bbc-news",
                "name": "BBC News"
            },
            "author": "BBC News",
            "title": "Measles returns to four European nations, WHO says",
            "url": "http://www.bbc.co.uk/news/health-49507253"
        },
    etc......

当然,我创建了描述Article,Source和News的类。新闻有文章列表。

我只想解析前五篇文章并将其保存到列表中。我知道我必须使用For循环,但是我该怎么做?我尝试使用以下代码:

public News parseFive() {
    List<Article> articleList = null;

    for(int i = 0; i<5; i++) {
        articleList = Arrays.asList(
        new Article(restTemplate.getForObject
                                ("https://newsapi.org/v2/top-headlines?sources=bbc-news&apiKey=19acc3a371d145ecb37a093f9985ea21", Article.class)));
    }
    News news = new News();
    news.setArticles(articleList);
    return news;
}

新闻课是:

public class News {

    private int totalResults;

    private List<Article> articles;

    public News() {

    }

    public int getTotalResults() {
        return totalResults;
    }

    public void setTotalResults(int totalResults) {
        this.totalResults = totalResults;
    }

    public List<Article> getArticles() {
        return articles;
    }

    public void setArticles() {
        this.articles = articles;
    }
}

结果是:

{
    "totalResults": 0,
    "articles": [
        {
            "source": null,
            "author": null,
            "title": null,
            "url": null
        }
    ]
}

问题出在哪里?也许是因为发现的头等舱不是文章而是新闻?谢谢大家的努力。

1 个答案:

答案 0 :(得分:0)

在使用RestTemplate.getForObject时,从技术上讲,您正在解析整个响应:Spring读取所有字节并使用JSON解析器(Jackson)创建对象。您的for循环(稍后介绍)仅过滤掉5号以后的元素。如果您真的只想解析前5篇文章,则应考虑使用Jackson Streaming API。与RestTemplate结合使用时会出现问题,这很安静,请阅读this answer以获取更多信息。

现在让我们尝试修复您的parseFive

首先,创建一个类来捕获整个响应:

public class Response {
    private String status;
    private Integer totalResults;
    private List<Artice> articles;

    // Getters & Setters
}

现在,获得前五篇文章:

public News parseFive() {
    final Response response = restTemplate
        .getForObject("https://newsapi.org/v2/top-headlines?sources=bbc-news&apiKey=19acc3a371d145ecb37a093f9985ea21", Response.class);
    final News news = new News();

    news.setArticles(response.articles.stream().limit(5).collect(Collectors.toList());

    return news;
}

您尚未提供News类,可能与响应相同。然后,代码可能类似于:

public News parseFive() {
    final News news = restTemplate
        .getForObject("https://newsapi.org/v2/top-headlines?sources=bbc-news&apiKey=19acc3a371d145ecb37a093f9985ea21", Response.class);

    news.setArticles(news.articles.stream().limit(5).collect(Collectors.toList());

    return news;
}