WebClientでJSONオブジェクトのリストを取得する
1. 概要
私たちのサービスは、情報を取得するために他のRESTサービスと通信することがよくあります。
Spring 5から、 WebClient を使用して、これらのリクエストをリアクティブで非ブロッキングの方法で実行できるようになります。 WebClient は、 ProjectReactorの上に構築された新しいWebFluxフレームワークの一部です。 流暢でリアクティブなAPIを備えており、基盤となる実装でHTTPプロトコルを使用します。
Webリクエストを行うと、データはJSONとして返されることがよくあります。 WebClientはこれを変換できます。
この記事では、JSON配列をObjectのJavaArray 、POJOのArrayに変換する方法について説明します。 ]、およびWebClientを使用したPOJOのList。
2. 依存関係
WebClient、を使用するには、pom.xmlにいくつかの依存関係を追加する必要があります。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.projectreactor</groupId>
<artifactId>reactor-spring</artifactId>
<version>1.0.1.RELEASE</version>
</dependency>
3. JSON、POJO、およびサービス
エンドポイントhttp:// localhost:8080 / readers から始めましょう。このエンドポイントは、お気に入りの本を含むリーダーのリストをJSON配列として返します。
[{
"id": 1,
"name": "reader1",
"favouriteBook": {
"author": "Milan Kundera",
"title": "The Unbearable Lightness of Being"
}
}, {
"id": 2,
"name": "reader2"
"favouriteBook": {
"author": "Douglas Adams",
"title": "The Hitchhiker's Guide to the Galaxy"
}
}]
データを処理するには、対応するReaderおよびBookクラスが必要です。
public class Reader {
private int id;
private String name;
private Book favouriteBook;
// getters and setters..
}
public class Book {
private final String author;
private final String title;
// getters and setters..
}
インターフェイスの実装では、依存関係としてWebClientを使用してReaderConsumerServiceImplを記述します。
public class ReaderConsumerServiceImpl implements ReaderConsumerService {
private final WebClient webClient;
public ReaderConsumerServiceImpl(WebClient webclient) {
this.webclient = webclient;
}
// ...
}
4. JSONオブジェクトのリストのマッピング
RESTリクエストからJSON配列を受け取った場合、それをJavaコレクションに変換する方法は複数あります。 さまざまなオプションを見て、返されたデータの処理がいかに簡単かを見てみましょう。 読者のお気に入りの本を抽出する方法を見ていきます。
4.1. モノ対。 フラックス
Project Reactor は、 Publisherの2つの実装、MonoとFluxを導入しました。
フラックス
ユースケースのように、結果が一度に返されることがわかっている場合は、次を使用できます。 単核症
4.2. WebClientとObject配列
まず、WebClient.getでGET呼び出しを行い、タイプ Object[]のMonoを使用して応答を収集しましょう。
Mono<Object[]> response = webClient.get()
.accept(MediaType.APPLICATION_JSON)
.retrieve()
.bodyToMono(Object[].class).log();
次に、ボディをObjectの配列に抽出しましょう。
Object[] objects = response.block();
ここでの実際のObjectは、データを含む任意の構造です。 それをReaderオブジェクトの配列に変換してみましょう。
このためには、ObjectMapperが必要です。
ObjectMapper mapper = new ObjectMapper();
ここでは、インラインで宣言しましたが、これは通常、クラスの private staticfinalメンバーとして実行されます。
最後に、読者のお気に入りの本を抽出してリストにまとめる準備が整いました。
return Arrays.stream(objects)
.map(object -> mapper.convertValue(object, Reader.class))
.map(Reader::getFavouriteBook)
.collect(Collectors.toList());
JacksonデシリアライザーにターゲットタイプとしてObjectを生成するように依頼すると、実際にははJSONを一連のLinkedHashMapオブジェクトにデシリアライズします。 convertValueによる後処理は非効率的です。 デシリアライズ中にJacksonに目的のタイプを提供すれば、これを回避できます。
4.3. WebClientとリーダーアレイ
Object[]の代わりにReader[]をWebClientに提供できます。
Mono<Reader[]> response = webClient.get()
.accept(MediaType.APPLICATION_JSON)
.retrieve()
.bodyToMono(Reader[].class).log();
Reader[] readers = response.block();
return Arrays.stream(readers)
.map(Reader:getFavouriteBook)
.collect(Collectors.toList());
ここで、ObjectMapper.convertValueが不要になったことを確認できます。 ただし、Java Stream APIを使用し、コードを List で機能させるには、追加の変換を行う必要があります。
4.4. WebClientとリーダーリスト
Jacksonに配列の代わりにReaderのListを生成させたい場合は、作成するListを記述する必要があります。 これを行うために、匿名内部クラスによって生成されたParameterizedTypeReferenceをメソッドに提供します。
Mono<List<Reader>> response = webClient.get()
.accept(MediaType.APPLICATION_JSON)
.retrieve()
.bodyToMono(new ParameterizedTypeReference<List<Reader>>() {});
List<Reader> readers = response.block();
return readers.stream()
.map(Reader::getFavouriteBook)
.collect(Collectors.toList());
これにより、操作できるリストが得られます。
ParameterizedTypeReferenceを使用する必要がある理由を詳しく見ていきましょう。
SpringのWebClientは、実行時に型情報が利用できる場合、JSONをReader.classに簡単に逆シリアル化できます。
ただし、ジェネリック医薬品では型消去使用しようとすると発生しますリスト
ParameterizedTypeReference を使用することで、この問題を解決できます。 匿名の内部クラスとしてインスタンス化すると、ジェネリッククラスのサブクラスに、型消去の対象ではなく、リフレクションを通じて使用できるコンパイル時の型情報が含まれているという事実が利用されます。
5. 結論
このチュートリアルでは、を使用してJSONオブジェクトを処理する3つの異なる方法を見ました WebClient
次に、 ParameterizedTypeReference を使用して、Listを生成するための情報のタイプを提供する方法を学習しました。
いつものように、この記事のコードはGitHubでから入手できます。