【Java】JSONをJavaに、JavaをJSONにする　～GSONとJacksonの使用方法～

# 概要
JavaでWeb APIを利用するときに良く使う JSON→Java、Java→JSON のやり方についてまとめます
また、JSONをHTTP POSTしたりHTTP GETしたりする方法は次の記事でまとめます。

- <b>【本稿】JavaでJSONを扱う方法についてまとめます</b>
    - JSONをJavaに変換(デシリアライズ)、JavaをJSONに変換(シリアライズ)するやり方は2通り説明します
        - ライブラリにGSONを使うやり方
        - ライブラリにJacksonを使うやり方

- [【次稿】JavaでHTTP通信でJSONをPOSTしたり、GETしたりする方法についてもまとめます](https://qiita.com/riversun/items/4e0a1b6bea42ae1405c4)
    - JavaでHTTP通信をするやり方も2通り説明します
        - OkHttp3を使ったやり方
        - Java標準パッケージである**HttpUrlConnection**を使ったやり方

# 最短コース　～JSONありきで考える～

外部APIをたたく時など、パースしたいJSON文字列が既に存在していた場合の最短コースで考える。
モデルクラスの[**自動生成サイト**](http://www.jsonschema2pojo.org/)を活用するので、JSONの文字列があればOK(JSON schemaがあれば尚よい)。


```json:サンプルのJSON文字列：example.json
{
    "person": {
        "firstName": "John",
        "lastName": "Doe",
        "address": "NewYork",
        "pets": [
            {"type": "Dog", "name": "Jolly"},
            {"type": "Cat", "name": "Grizabella"},
            {"type": "Fish", "name": "Nimo"}
        ]
    }
}
```

# GSONとJackson

JavaでJSON操作というと**GSON**と**Jackson**の2つのライブラリを良く使う。
どちらが良いと一概に言えないので両方説明する。

**GSON**
Google製の[ライブラリ](https://github.com/google/gson)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170905/347df570-a790-3b9a-8961-15c3d8233afb.png)

**Jackson**
パフォーマンスを重視した[ライブラリ](https://github.com/FasterXML/jackson)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170905/823fd5fe-2bad-eac0-74f5-27611ae2d62d.png)

# GSON編

## **GSON**をつかってJSONをJavaにマッピングする

まずGSONから見ていく。JSONありき、つまり生のJSON文字列からJavaのパーサーを作ろうっていう場合はjsonschema2pojoを使うとお手軽なのでやってみる。

本章のソースコードはこちら
https://github.com/riversun/java-json-gson-jackson-http/tree/master/src/main/java/com/example/gson

## GSONのライブラリ依存関係

GSONのライブラリ指定方法は以下のとおり

■ GSONの最新ライブラリ(mavenリポジトリ)
https://mvnrepository.com/artifact/com.google.code.gson/gson

■ GSONの**maven**設定例

```xml:pom.xml
<dependency>
	<groupId>com.google.code.gson</groupId>
	<artifactId>gson</artifactId>
	<version>2.8.5</version>
</dependency>
```

■ GSONの**gradle**設定例

```groovy:build.gradle
compile 'com.google.code.gson:gson:2.8.5'
```


### (1) jsonschema2pojoを使ってモデルクラス(POJO)を自動生成する

以下のサイトにいって、ペタッと上のJSONを貼る
http://www.jsonschema2pojo.org/

※外部サイトに抵抗がある場合は、[ライブラリ](https://github.com/joelittlejohn/jsonschema2pojo/)を使って自前でやることも可能


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170905/1c23c4cc-3817-70e5-5f70-d976b2dc8d77.png)

■ サイト上で以下のように設定して、**Zip**を押すとモデルクラスが自動生成される

Package:**com.example.gson** (パッケージ名、何でも良いが、そのパッケージ名付でソースが自動生成される）
ClassN name:**Model** (Pojoの最上位のクラス名)
Target language:**Java**
Source type:**JSON**(JSON文字列そのものからモデルクラスを推定する)
Annotation style:**Gson**(パーサーにGSONを使う)
☑**Allow additional properties**(JSONに未知のものが混ざっていてもOK)

**Zip**ファイルが生成されるので、ダウンロードして開くと、以下のように3つのjavaファイルが自動生成されている。

### (2) **自動生成**されたモデルクラス(POJO)を確認

■ **Model.java**・・・一番上位となるクラス

```java:Model.java
package com.example.gson;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Model {
    @SerializedName("person")
    @Expose
    public Person person;
}
```

■ **Person.java**・・・**"pets":[]**のように配列指定されたものは**List**になる

```java:Person.java
package com.example.gson;
import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Person {
    @SerializedName("firstName")
    @Expose
    public String firstName;
    @SerializedName("lastName")
    @Expose
    public String lastName;
    @SerializedName("address")
    @Expose
    public String address;
    @SerializedName("pets")
    @Expose
    public List<Pet> pets = null;
}
```

■ **Pet.java**

```java:Pet.java
package com.example.gson;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Pet {
    @SerializedName("type")
    @Expose
    public String type;
    @SerializedName("name")
    @Expose
    public String name;
}
```

### (3)  GSONを使って、**JSON→Java**の変換

JSONからJavaへの変換、つまりGSONを使ってJSON文字列をJavaのモデルクラスに読み込む
ポイントとなるコードは以下のようになる

```java
Gson gson = new Gson();
Model model = gson.fromJson(json, Model.class);
```

コード全体は以下のようになる

■ **GsonJson2Java.java**

```java:GsonJson2.java
package com.example.gson;

import com.google.gson.Gson;

public class GsonJson2Java {
    public static void main(String[] args) {
        String json = 
                "{" +
                "    \"person\": {" +
                "        \"firstName\": \"John\"," +
                "        \"lastName\": \"Doe\"," +
                "        \"address\": \"NewYork\"," +
                "        \"pets\": [" +
                "            {\"type\": \"Dog\", \"name\": \"Jolly\"}," +
                "            {\"type\": \"Cat\", \"name\": \"Grizabella\"}," +
                "            {\"type\": \"Fish\", \"name\": \"Nimo\"}" +
                "        ]" +
                "    }" +
                "}";

        Gson gson = new Gson();
        Model model = gson.fromJson(json, Model.class);

        System.out.println("firstName:" + model.person.firstName);
        System.out.println("lastName:" + model.person.lastName);
        System.out.println("address:" + model.person.address);
        System.out.println("1st pet:" + model.person.pets.get(0).name);
    }
}

```

```shell:実行結果
firstName:John
lastName:Doe
address:NewYork
1st pet:Jolly
```


### (4) GSONを使って、**Java→JSON**の変換

さて、今度は JavaからJSONをやる。Javaのモデルクラス(POJO)をJSON化する。

```java
Gson gson = new Gson();
String json = gson.toJson(model);
```


**GsonJava2Json.java**

```java:GsonJava2Json.java
package com.example.gson;

import java.util.ArrayList;
import com.google.gson.Gson;

public class GsonJava2Json {
    public static void main(String[] args) {

        Model model = new Model();
        model.person = new Person();
        model.person.firstName = "ジョン";
        model.person.lastName = "ドゥ";
        model.person.address = "ニューヨーク";

        model.person.pets = new ArrayList<Pet>();

        Pet pet1 = new Pet();
        pet1.type = "犬";
        pet1.name = "ジョリー";
        model.person.pets.add(pet1);

        Pet pet2 = new Pet();
        pet2.type = "猫";
        pet2.name = "グリザベラ";
        model.person.pets.add(pet2);

        Pet pet3 = new Pet();
        pet3.type = "魚";
        pet3.name = "ニモ";
        model.person.pets.add(pet3);

        Gson gson = new Gson();
        String json = gson.toJson(model);

        System.out.println(json);
    }
}
```

これを実行すると以下の通りモデルクラスからJSONを出力できた

```shell:実行結果
{"person":{"firstName":"ジョン","lastName":"ドゥ","address":"ニューヨーク","pets":[{"type":"犬","name":"ジョリー"},{"type":"猫","name":"グリザベラ"},{"type":"魚","name":"ニモ"}]}}

```

### (5) GSONを使って、JSONを整形(Pretty Printing)して出力

このようにすると、JSONがインデントされキレイにフォーマットされて出てくる

```java
Gson gson2 = new GsonBuilder().setPrettyPrinting().create();
String prettyJson = gson2.toJson(model);
System.out.println(prettyJson);
```

実行結果

```shell
{
  "person": {
    "firstName": "ジョン",
    "lastName": "ドゥ",
    "address": "ニューヨーク",
    "pets": [
      {
        "type": "犬",
        "name": "ジョリー"
      },
      {
        "type": "猫",
        "name": "グリザベラ"
      },
      {
        "type": "魚",
        "name": "ニモ"
      }
    ]
  }
}
```

<hr>

# Jackson編

Jacksonは1.x系と2.x系があるが、2.x系を使う

## **Jackson**をつかってJSONをJavaにマッピングする

本章のソースコードはこちら
https://github.com/riversun/java-json-gson-jackson-http/tree/master/src/main/java/com/example/jackson

## Jacksonのライブラリ依存関係

Jacksonのライブラリ指定方法は以下のとおり

■ Jacksonの最新ライブラリ(mavenリポジトリ)
https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind

■ Jacksonの**maven**設定例

```xml:pom.xml
<dependency>
	<groupId>com.fasterxml.jackson.core</groupId>
	<artifactId>jackson-databind</artifactId>
	<version>2.9.8</version>
</dependency>
```

■ Jacksonの**gradle**設定例

```groovy:build.gradle
compile 'com.fasterxml.jackson.core:jackson-databind:2.9.8'
```

### (1) jsonschema2pojoを使ってモデルクラス(POJO)を自動生成する

以下のサイトにいって、ペタッと上のJSONを貼る
http://www.jsonschema2pojo.org/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170905/d0fd85b4-44e2-60d9-78bc-53b016eea942.png)

■ サイト上で以下のように設定して、**Zip**を押すとモデルクラスが自動生成される

Package:**com.example.<font color=red>jackson</font>** (パッケージ名、何でも良いが、そのパッケージ名付でソースが自動生成される）
ClassN name:**Model** (Pojoの最上位のクラス名)
Target language:**Java**
Source type:**JSON**(JSON文字列そのものからモデルクラスを推定する)
Annotation style:<font color=red>**jackson 2.x**</font>(パーサーにJackson 2.xを使う)
☑**Allow additional properties**(JSONに未知のものが混ざっていてもOK)

**Zip**ファイルが生成されるので、ダウンロードして開くと、以下のように3つのjavaファイルが自動生成されている。

### (2) **自動生成**されたモデルクラス(POJO)を確認

■ **Model .java**・・・一番上位となるクラス。追加プロパティを受け入れるために、**@JsonAnyGetter**をセットしている点が特徴的。また、その為に、GSONよりも冗長になる。

```java:Model.java
package com.example.jackson;
import java.util.HashMap;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({
    "person"
})
public class Model {
    @JsonProperty("person")
    public Person person;
    @JsonIgnore
    private Map<String, Object> additionalProperties = new HashMap<String, Object>();
    @JsonAnyGetter
    public Map<String, Object> getAdditionalProperties() {
        return this.additionalProperties;
    }
    @JsonAnySetter
    public void setAdditionalProperty(String name, Object value) {
        this.additionalProperties.put(name, value);
    }
}
```

■ **Person.java**・・・**@JsonPropertyOrder**で出現順序を拘束できる。**"pets":[]**のように配列指定されたものは**List**になる。

```java:Person.java
package com.example.jackson;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({
    "firstName",
    "lastName",
    "address",
    "pets"
})
public class Person {
    @JsonProperty("firstName")
    public String firstName;
    @JsonProperty("lastName")
    public String lastName;
    @JsonProperty("address")
    public String address;
    @JsonProperty("pets")
    public List<Pet> pets = null;
    @JsonIgnore
    private Map<String, Object> additionalProperties = new HashMap<String, Object>();
    @JsonAnyGetter
    public Map<String, Object> getAdditionalProperties() {
        return this.additionalProperties;
    }
    @JsonAnySetter
    public void setAdditionalProperty(String name, Object value) {
        this.additionalProperties.put(name, value);
    }
}

```

■ **Pet.java**

```java:Pet.java
package com.example.jackson;
import java.util.HashMap;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({
    "type",
    "name"
})
public class Pet {
    @JsonProperty("type")
    public String type;
    @JsonProperty("name")
    public String name;
    @JsonIgnore
    private Map<String, Object> additionalProperties = new HashMap<String, Object>();
    @JsonAnyGetter
    public Map<String, Object> getAdditionalProperties() {
        return this.additionalProperties;
    }
    @JsonAnySetter
    public void setAdditionalProperty(String name, Object value) {
        this.additionalProperties.put(name, value);
    }
}
```

### (3) Jacksonを使って、**JSON→Java**の変換

JSONからJavaへの変換、つまりJacksonを使ってJSON文字列をJavaのモデルクラスに読み込む
ポイントとなるコードは以下のようになる

```java
ObjectMapper mapper = new ObjectMapper();
Model model = mapper.readValue(json, Model.class);
```

コード全体は以下のようになる

■ **JacksonJson2Java.java**

```JacksonJson2Java.java
package com.example.jackson;

import java.io.IOException;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class JacksonJson2Java {
    public static void main(String[] args) throws JsonParseException, JsonMappingException, IOException {
        String json = "{" +
                "    \"person\": {" +
                "        \"firstName\": \"John\"," +
                "        \"lastName\": \"Doe\"," +
                "        \"address\": \"NewYork\"," +
                "        \"pets\": [" +
                "            {\"type\": \"Dog\", \"name\": \"Jolly\"}," +
                "            {\"type\": \"Cat\", \"name\": \"Grizabella\"}," +
                "            {\"type\": \"Fish\", \"name\": \"Nimo\"}" +
                "        ]" +
                "    }" +
                "}";

        ObjectMapper mapper = new ObjectMapper();
        Model model = mapper.readValue(json, Model.class);

        System.out.println("firstName:" + model.person.firstName);
        System.out.println("lastName:" + model.person.lastName);
        System.out.println("address:" + model.person.address);
        System.out.println("1st pet:" + model.person.pets.get(0).name);
    }
}
```

### (4) Jacksonを使って、**Java→JSON**の変換

さて、今度は JavaからJSONをやる。Javaのモデルクラス(POJO)をJSON化する。

```java
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(model);
```

**JacksonJava2Json.java**

```JacksonJava2Json.java
package com.example.jackson;
import java.util.ArrayList;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class JacksonJava2Json {
    public static void main(String[] args) throws JsonProcessingException {

        Model model = new Model();
        model.person = new Person();
        model.person.firstName = "ジョン";
        model.person.lastName = "ドゥ";
        model.person.address = "ニューヨーク";
        model.person.pets = new ArrayList<Pet>();
        Pet pet1 = new Pet();
        pet1.type = "犬";
        pet1.name = "ジョリー";
        model.person.pets.add(pet1);
        Pet pet2 = new Pet();
        pet2.type = "猫";
        pet2.name = "グリザベラ";
        model.person.pets.add(pet2);
        Pet pet3 = new Pet();
        pet3.type = "魚";
        pet3.name = "ニモ";
        model.person.pets.add(pet3);

        ObjectMapper mapper = new ObjectMapper();
        String json = mapper.writeValueAsString(model);
        System.out.println(json);
    }
}
```

これを実行すると以下の通りモデルクラスからJSONを出力できた

```shell:実行結果
{"person":{"firstName":"ジョン","lastName":"ドゥ","address":"ニューヨーク","pets":[{"type":"犬","name":"ジョリー"},{"type":"猫","name":"グリザベラ"},{"type":"魚","name":"ニモ"}]}}
```

### (5) Jacksonを使って、JSONを整形(Pretty Printing)して出力

このようにすると、JSONがインデントされキレイにフォーマットされて出てくる

```java
ObjectMapper mapper2 = new ObjectMapper();
String prettyJson = mapper2.writerWithDefaultPrettyPrinter().writeValueAsString(model);
System.out.println(prettyJson);
```

実行結果

```shell
{
  "person" : {
    "firstName" : "ジョン",
    "lastName" : "ドゥ",
    "address" : "ニューヨーク",
    "pets" : [ {
      "type" : "犬",
      "name" : "ジョリー"
    }, {
      "type" : "猫",
      "name" : "グリザベラ"
    }, {
      "type" : "魚",
      "name" : "ニモ"
    } ]
  }
}

```

# まとめ
- GSONをつかってJSON→Java、Java→JSONをお手軽に実行する方法を説明しました
    - GSONを使ったソースコードは[こちら](https://github.com/riversun/java-json-gson-jackson-http/tree/master/src/main/java/com/example/gson)です

- Jacksonの場合も同様に説明しました
    - Jacksonを使ったソースコードは[こちら](https://github.com/riversun/java-json-gson-jackson-http/tree/master/src/main/java/com/example/jackson)です
- JSONをHTTP通信でPOSTやGETする方法は[こちら](https://qiita.com/riversun/items/4e0a1b6bea42ae1405c4)にまとめました