Jacksonで配列JSONをJavaBeanの配列又はListに変換する

[Jackson](https://github.com/FasterXML/jackson)を使用して配列JSONを、任意のJavaBean配列や`java.util.List<T>`として読み込む方法を紹介します。

今回は、以下のようなJSONをJavaBean(`Todo`)の配列やリストにマッピングして読み込みます。

* 配列JSON

```json
[
  {
    "title" : "Jsckson勉強会"
  }
  ,
  {
    "title" : "飲み会"
  }
]
```

* JavaBean(`Todo`)

```java
public class Todo {
    private String title;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}
```

# 動作検証バージョン

* Jackson 2.6.7
* Spring Boot 1.3.6.RELEASE

# 検証コード

* https://github.com/kazuki43zoo/qiita-materials/tree/master/spring-mvc/json-demo

# JSONを読み込む

実際にJunitを作って動かしてみます。なお、Junitで作っていますが、今回はAssertは省略させてもらいます。

```java
package com.example;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Test;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;


public class ObjectMapperJsonArrayTests {

    private static final String ARRAY_JSON = new StringBuilder()
            .append("[")
            .append("  {")
            .append("    \"title\" : \"Jsckson勉強会\"")
            .append("  }")
            .append("  ,")
            .append("  {")
            .append("    \"title\" : \"飲み会\"")
            .append("  }")
            .append("]").toString();

    private final ObjectMapper jsonMapper = new ObjectMapper();

    /**
     * 配列として読み込む
     */
    @Test
    public void array() throws IOException {
        Todo[] todoArray = jsonMapper.readValue(ARRAY_JSON, Todo[].class);
        for (Todo todo : todoArray) {
            System.out.println(todo.getTitle());
        }
    }

    /**
     * 配列として読み込みArrays#asListでリスト化する
     */
    @Test
    public void arrayConvertListUsingArraysAsList() throws IOException {
        List<Todo> todoList = Arrays.asList(jsonMapper.readValue(ARRAY_JSON, Todo[].class));
        for (Todo todo : todoList) {
            System.out.println(todo.getTitle());
        }
    }

    /**
     * TypeReferenceを使用してリストとして読み込む
     */
    @Test
    public void listUsingTypeReference() throws IOException {
        List<Todo> todoList = jsonMapper.readValue(ARRAY_JSON, new TypeReference<List<Todo>>() {});
        for (Todo todo : todoList) {
            System.out.println(todo.getTitle());
        }
    }

    static class Todo {
        private String title;

        public String getTitle() {
            return title;
        }

        public void setTitle(String title) {
            this.title = title;
        }
    }

}
```

このテストケースを実行すると・・・

```text:コンソール
Jsckson勉強会
飲み会
Jsckson勉強会
飲み会
Jsckson勉強会
飲み会
```

という感じで標準出力に読み込んだ内容が出力されます。

## 配列として読み込む

一番シンプルな読み込み方法です。メソッド内の処理だけで使う＋拡張For文などで単純な繰り返し処理を行うだけなら配列でもよいと思います。

```java
Todo[] todoArray = jsonMapper.readValue(ARRAY_JSON, Todo[].class);
```

## 配列として読み込み`Arrays#asList`でリスト化する

読み込んだ配列をメソッドの返り値として返却するような場合は、配列ではなくリストを使うのが一般的でしょう。そんな時は、`java.util.Arrays#asList(T...)`を使うと簡単にリスト化できます。なお、この方法でリスト化すると、リストに対して要素の追加や削除などができないリストが生成されます。（要素を追加、削除すると`java.lang.UnsupportedOperationException`が発生します）

```java
List<Todo> todoList = Arrays.asList(jsonMapper.readValue(ARRAY_JSON, Todo[].class));
```

## `TypeReference`を使用してリストとして読み込む

リストとして読み込む方法もあります。リストとして読み込む場合は、読み込みたい型を`com.fasterxml.jackson.core.type.TypeReference`の型パラメータに指定します。この方法で生成したリストに対しては、要素の追加や削除もできます。

```java
List<Todo> todoList = jsonMapper.readValue(ARRAY_JSON, new TypeReference<List<Todo>>() {});
```

# まとめ

本投稿では３つの方法（配列方式、配列->リスト変換方式、リスト方式）を紹介しました。
これは個人的な意見ですが、`TypeReference`方式はなんとなく直感的じゃない気がしてあまり好きじゃない・・・。初見だと・・・`TypeReference`って何者だろ〜と思う方もいるのでは？？？
であれば、Javaの標準APIを使ってリスト化する方がわかりやすいと思います。（あくまで個人的な意見です。 :wink: ）