Spring WebClient检索封装在results属性下的json对象



我目前正在开发一个Spring Boot应用程序,将一个外部REST API封装到我自己的GraphQL API中。

到目前为止,我已经做了这个方法返回一个SerieDetails:
public SerieDetails findOrThrow(long id) throws RuntimeException {
try {
return this.webClient
.get()
.uri("/tv/{id}?api_key={apiKey}&language={lang}", id, this.apiKey, this.lang)
.retrieve()
.bodyToMono(SerieDetails.class)
.log()
.block();
} catch(Exception e ) {
throw new RuntimeException("Can't reach the API");
}
}

将JSON转换为我自己的对象:

{
"id": 71912,
"name": "The Witcher",
"overview": "Geralt of Rivia, a mutated monster-hunter for hire, journeys toward his destiny in a turbulent world where people often prove more wicked than beasts."
"last_air_date": "2019-12-20",
...
}

效果很好。但现在我正在做另一个调用,返回一个给定查询的SerieDetails列表,它返回result数组下的结果:

{
"page": 1,
"results": [
{
"id": 71912,
"name": "The Witcher",
"overview": "Geralt of Rivia, a mutated monster-hunter for hire, journeys toward his destiny in a turbulent world where people often prove more wicked than beasts."
"first_air_date": "2019-12-20",
...
},
{
"id": 106541,
"name": "The Witcher: Blood Origin",
"overview": "Set in an elven world 1200 years before the world of The Witcher, the show charts the origins of the very first Witcher, and the events that lead to the pivotal “conjunction of the spheres,” when the worlds of monsters, men, and elves merged to become one.",
"first_air_date": "2002-09-22",
...
}
]
}

我不知道如何使用WebClient来访问它。我试过了:

public List<SerieDetails> findByQuery(String query) {
return this.webClient
.get()
.uri("/search/tv?api_key={apiKey}&language={lang}&query={query}", this.apiKey, this.lang, query)
.retrieve()
.bodyToFlux(SerieDetails.class)
.log()
.collect(Collectors.toList())
.block();
}

但是行不通。

您需要更改JSON反序列化到的对象。函数bodyToMonobodyToFlux创建两个不同的流,其中MonoFlux是发布者:

  • Mono最多排放一项;
  • Flux发出从0到N项的序列。

项是指定类的实例。在您的示例中,将JSON响应转换为SerieDetails。多个项目并不意味着一个SerieDetails的数组,而是多个具有SerieDetails结构的JSON响应。你可以把它想象成同一个类的不同对象实例。

更简单的解决方案是创建以下类:
class PaginatedSerieDetails {
private int page;
private List<SerieDetails> results;
// getters and setters
}

那么当你按如下方式调用时,你会使用这个:

public List<SerieDetails> findByQuery(String query) {
return this.webClient
.get()
.uri("/search/tv?api_key={apiKey}&language={lang}&query={query}", this.apiKey, this.lang, query)
.retrieve()
.bodyToMono(PaginatedSerieDetails.class)
.map(PaginatedSerieDetails::getResults())
.log()
.block();
}

作为旁注,请在使用WebFlux时尽量避免.block()。当你这样做的时候,你就违背了使用响应式堆栈的全部目的,因为你说你实际上是想让线程等待Mono或Flux发出一个值。

相关内容

  • 没有找到相关文章

最新更新