Spring Framework の RestTemplate で JSON を Object 型またはその配列で取得する

## 概要

- Spring Framework の RestTemplate で JSON を取得し、Object 型または Object 型の配列で取得する
- 取得したオブジェクトが実際にはどの型にマッピングされているか検証する
- 検証環境: Spring Boot 2.5.0 + Java 11 (AdoptOpenJDK-11.0.11+9)

## ソースコード

ここではコントローラークラスのみ示す。

```java
package org.example;

import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class MyController {

  // 指定された URL から JSON を取得し Object 型で受け取ってそのまま返す
  @GetMapping("/object-proxy")
  public Object objectProxy(@RequestParam String url) {
    RestTemplate rest = new RestTemplate();
    RequestEntity<Void> req = RequestEntity.get(url).build();
    ResponseEntity<Object> res = rest.exchange(req, Object.class);
    Object body = res.getBody();
    System.out.println("objectProxy");
    System.out.println("body: " + body.getClass()); // 実際のクラスを確認する
    return body;
  }

  // 指定された URL から JSON を取得し Object 型の配列で受け取ってそのまま返す
  @GetMapping("/array-proxy")
  public Object[] arrayProxy(@RequestParam String url) {
    RestTemplate rest = new RestTemplate();
    RequestEntity<Void> req = RequestEntity.get(url).build();
    ResponseEntity<Object[]> res = rest.exchange(req, Object[].class);
    Object[] body = res.getBody();
    System.out.println("arrayProxy");
    System.out.println("body: " + body.getClass()); // 実際のクラスを確認する
    for (Object obj : body) {
      System.out.println("obj: " + obj.getClass()); // 実際のクラスを確認する
    }
    return body;
  }

  // JSON オブジェクトを返す (Content-Type は指定せず)
  @GetMapping("/object")
  public String getJsonObject() {
    return "{\"name\": \"Alice\"}";
  }

  // JSON 配列を返す (Content-Type は指定せず)
  @GetMapping("/array")
  public String getJsonArray() {
    return "[{\"name\": \"Alice\"},{\"name\": \"Bob\"}]";
  }
}
```



## 検証

curl コマンドでエンドポイントにアクセスして検証する。

### JSON オブジェクトを返すエンドポイント

JSON オブジェクトを取得。
Content-Type を指定していないため text/plain になっている。

```
$ curl --include http://localhost:8080/object
HTTP/1.1 200 
Content-Type: text/plain;charset=UTF-8
Content-Length: 17
Date: Sat, 05 Jun 2021 08:00:05 GMT

{"name": "Alice"}
```

### JSON 配列を返すエンドポイント

JSON 配列を取得。
Content-Type を指定していないため text/plain になっている。

```
$ curl --include http://localhost:8080/array
HTTP/1.1 200 
Content-Type: text/plain;charset=UTF-8
Content-Length: 35
Date: Sat, 05 Jun 2021 08:00:09 GMT

[{"name": "Alice"},{"name": "Bob"}]
```

### JSON オブジェクトを取得し Java の Object 型で受け取ってそのまま返す

JSON オブジェクトを返すエンドポイントから JSON を取得し、Java の Object 型で受け取ってそのまま返している。

```
$ curl --include http://localhost:8080/object-proxy --get --data-urlencode "url=http://localhost:8080/object"
HTTP/1.1 200 
Content-Type: application/json
Transfer-Encoding: chunked
Date: Sat, 05 Jun 2021 08:00:15 GMT

{"name":"Alice"}
```

Spring Boot 側のログを見る。
Object 型で取得した JSON オブジェクトが、実際には LinkedHashMap になっていることがわかる。

```
objectProxy
body: class java.util.LinkedHashMap
```

### JSON 配列を取得し Java の Object 型の配列で受け取ってそのまま返す

JSON 配列を返すエンドポイントから JSON を取得し、Java の Object 型の配列で受け取ってそのまま返している。

```
$ curl --include http://localhost:8080/array-proxy --get --data-urlencode "url=http://localhost:8080/array"
HTTP/1.1 200 
Content-Type: application/json
Transfer-Encoding: chunked
Date: Sat, 05 Jun 2021 08:00:21 GMT

[{"name":"Alice"},{"name":"Bob"}]
```

Spring Boot 側のログを見る。
Object 型の配列で取得した JSON 配列が、LinkedHashMap を要素に持つ Object 側の配列になっていることがわかる。

```
arrayProxy
body: class [Ljava.lang.Object;
obj: class java.util.LinkedHashMap
obj: class java.util.LinkedHashMap
```

### JSON 配列を取得し Java の Object 型で受け取ってそのまま返す

JSON 配列を返すエンドポイントから JSON を取得し、Java の Object 型で受け取ってそのまま返している。

```
$ curl --include http://localhost:8080/object-proxy --get --data-urlencode "url=http://localhost:8080/array"
HTTP/1.1 200 
Content-Type: application/json
Transfer-Encoding: chunked
Date: Sat, 05 Jun 2021 08:00:27 GMT

[{"name":"Alice"},{"name":"Bob"}]
```

Spring Boot 側のログを見る。
Object 型で取得したオブジェクトが、実際には ArrayList になっていることがわかる。

```
objectProxy
body: class java.util.ArrayList
```

## 参考資料

- [RestTemplate \(Spring Framework 5\.3\.7 API\) \- Javadoc](https://spring.pleiades.io/spring-framework/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html)
- [curl \- How To Use](https://curl.se/docs/manpage.html)