前回は、Jackson単体で「配列JSONをJavaBeanの配列又はListに変換する方法」を紹介しました。今回は、Spring MVCとSpring Webから提供されているRestTemplate
で「配列JSONをJavaBeanの配列又はListに変換する方法」を紹介したいと思います。
前回と同様に、以下のようなJSONをJavaBean(Todo
)の配列やリストにマッピングします。
- 配列JSON
[
{
"title" : "Jsckson勉強会"
}
,
{
"title" : "飲み会"
}
]
- JavaBean(
Todo
)
public class Todo {
private String title;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
動作検証バージョン
- Spring Boot 1.3.6.RELEASE
- Spring Framework 4.2.7.RELEASE
- Jackson 2.6.7
検証コード
Spring MVCで配列JSONを読み込む
リクエストBODYに設定された配列JSONを、Spring MVCのHandlerメソッドの引数(JavaBeanのリスト)として受け取り方法をみていきましょう。
Handlerメソッドの引数として受け取り場合は、引数の型をList<T>
とし、引数に@org.springframework.web.bind.annotation.RequestBody
するだけで実現できます
@RequestMapping(path = "/api/v1/todos", method = RequestMethod.POST)
public List<Todo> post(@RequestBody List<Todo> todos) {
return todos;
}
RestTemplate
で配列JSONを読み込む
実際にRestTemplate
経由でSpring MVCのHandlerメソッドを呼び出してみます。なお、Junitで作っていますが、今回はAssertは省略させてもらいます。
package com.example;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.boot.test.WebIntegrationTest;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.web.client.RestTemplate;
import java.io.IOException;
import java.net.URI;
import java.util.Arrays;
import java.util.List;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = JsonDemoApplication.class)
@WebIntegrationTest(randomPort = true)
public class SpringWebMvcJsonArrayTests {
@Value("http://localhost:${local.server.port}/api/v1/todos")
private URI uri;
private final RestTemplate restTemplate = new RestTemplate();
private final List<Todo> requestTodoList = Arrays.asList(
new Todo("Jsckson勉強会")
, new Todo("飲み会")
);
/**
* 配列として読み込む
*/
@Test
public void array() throws IOException {
Todo[] todoArray = restTemplate.postForObject(uri, requestTodoList, Todo[].class);
for (Todo todo : todoArray) {
System.out.println(todo.getTitle());
}
}
/**
* 配列として読み込みArrays#asListでリスト化する
*/
@Test
public void arrayConvertListUsingArraysAsList() {
List<Todo> todoList = Arrays.asList(restTemplate.postForObject(uri, requestTodoList, Todo[].class));
for (Todo todo : todoList) {
System.out.println(todo.getTitle());
}
}
/**
* ParameterizedTypeReferenceを使用してリストとして読み込む
*/
@Test
public void listUsingParameterizedTypeReference() {
RequestEntity<List<Todo>> requestEntity = RequestEntity.post(uri).body(requestTodoList);
ResponseEntity<List<Todo>> responseEntity = restTemplate.exchange(requestEntity, new ParameterizedTypeReference<List<Todo>>() {});
for (Todo todo : responseEntity.getBody()) {
System.out.println(todo.getTitle());
}
}
}
配列として読み込む
一番シンプルな読み込み方法です。メソッド内の処理だけで使う+拡張For文などで単純な繰り返し処理を行うだけなら配列でもよいと思います。
Todo[] todoArray = restTemplate.postForObject(uri, requestTodoList, Todo[].class);
配列として読み込みArrays#asList
でリスト化する
読み込んだ配列をメソッドの返り値として返却するような場合は、配列ではなくリストを使うのが一般的でしょう。そんな時は、java.util.Arrays#asList(T...)
を使うと簡単にリスト化できます。なお、この方法でリスト化すると、リストに対して要素の追加や削除などができないリストが生成されます。(要素を追加、削除するとjava.lang.UnsupportedOperationException
が発生します)
List<Todo> todoList = Arrays.asList(restTemplate.postForObject(uri, requestTodoList, Todo[].class));
ParameterizedTypeReference
を使用してリストとして読み込む
リストとして読み込む方法もあります。リストとして読み込む場合は、読み込みたい型をorg.springframework.core.ParameterizedTypeReference
の型パラメータに指定します。この方法で生成したリストに対しては、要素の追加や削除もできます。
ResponseEntity<List<Todo>> responseEntity =
restTemplate.exchange(requestEntity, new ParameterizedTypeReference<List<Todo>>() {});
まとめ
Spring MVCの方はHandlerメソッドの引数にリストを宣言するだけなので非常にGoodです
RestTemplate
の方は、前回紹介した(Jackson単体での実装方法)とほとんど同じですね。やっぱりParameterizedTypeReference
(TypeReference
)はあまり好きになれないな〜