概要
JavaでWeb APIを利用するときに良く使う JSON→Java、Java→JSON のやり方についてまとめます
また、JSONをHTTP POSTしたりHTTP GETしたりする方法は次の記事でまとめます。
-
【本稿】JavaでJSONを扱う方法についてまとめます
- JSONをJavaに変換(デシリアライズ)、JavaをJSONに変換(シリアライズ)するやり方は2通り説明します
- ライブラリにGSONを使うやり方
- ライブラリにJacksonを使うやり方
- JSONをJavaに変換(デシリアライズ)、JavaをJSONに変換(シリアライズ)するやり方は2通り説明します
-
【次稿】JavaでHTTP通信でJSONをPOSTしたり、GETしたりする方法についてもまとめます
- JavaでHTTP通信をするやり方も2通り説明します
- OkHttp3を使ったやり方
- Java標準パッケージであるHttpUrlConnectionを使ったやり方
- JavaでHTTP通信をするやり方も2通り説明します
最短コース ~JSONありきで考える~
外部APIをたたく時など、パースしたいJSON文字列が既に存在していた場合の最短コースで考える。
モデルクラスの自動生成サイトを活用するので、JSONの文字列があればOK(JSON schemaがあれば尚よい)。
{
"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製のライブラリ
Jackson
パフォーマンスを重視したライブラリ
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設定例
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
</dependency>
■ GSONのgradle設定例
compile 'com.google.code.gson:gson:2.8.5'
(1) jsonschema2pojoを使ってモデルクラス(POJO)を自動生成する
以下のサイトにいって、ペタッと上のJSONを貼る
http://www.jsonschema2pojo.org/
※外部サイトに抵抗がある場合は、ライブラリを使って自前でやることも可能
■ サイト上で以下のように設定して、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・・・一番上位となるクラス
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になる
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
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のモデルクラスに読み込む
ポイントとなるコードは以下のようになる
Gson gson = new Gson();
Model model = gson.fromJson(json, Model.class);
コード全体は以下のようになる
■ GsonJson2Java.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);
}
}
firstName:John
lastName:Doe
address:NewYork
1st pet:Jolly
(4) GSONを使って、Java→JSONの変換
さて、今度は JavaからJSONをやる。Javaのモデルクラス(POJO)をJSON化する。
Gson gson = new Gson();
String json = gson.toJson(model);
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を出力できた
{"person":{"firstName":"ジョン","lastName":"ドゥ","address":"ニューヨーク","pets":[{"type":"犬","name":"ジョリー"},{"type":"猫","name":"グリザベラ"},{"type":"魚","name":"ニモ"}]}}
(5) GSONを使って、JSONを整形(Pretty Printing)して出力
このようにすると、JSONがインデントされキレイにフォーマットされて出てくる
Gson gson2 = new GsonBuilder().setPrettyPrinting().create();
String prettyJson = gson2.toJson(model);
System.out.println(prettyJson);
実行結果
{
"person": {
"firstName": "ジョン",
"lastName": "ドゥ",
"address": "ニューヨーク",
"pets": [
{
"type": "犬",
"name": "ジョリー"
},
{
"type": "猫",
"name": "グリザベラ"
},
{
"type": "魚",
"name": "ニモ"
}
]
}
}
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設定例
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
■ Jacksonのgradle設定例
compile 'com.fasterxml.jackson.core:jackson-databind:2.9.8'
(1) jsonschema2pojoを使ってモデルクラス(POJO)を自動生成する
以下のサイトにいって、ペタッと上のJSONを貼る
http://www.jsonschema2pojo.org/
■ サイト上で以下のように設定して、Zipを押すとモデルクラスが自動生成される
Package:com.example.jackson (パッケージ名、何でも良いが、そのパッケージ名付でソースが自動生成される)
ClassN name:Model (Pojoの最上位のクラス名)
Target language:Java
Source type:JSON(JSON文字列そのものからモデルクラスを推定する)
Annotation style:jackson 2.x(パーサーにJackson 2.xを使う)
☑Allow additional properties(JSONに未知のものが混ざっていてもOK)
Zipファイルが生成されるので、ダウンロードして開くと、以下のように3つのjavaファイルが自動生成されている。
(2) 自動生成されたモデルクラス(POJO)を確認
■ Model .java・・・一番上位となるクラス。追加プロパティを受け入れるために、@JsonAnyGetterをセットしている点が特徴的。また、その為に、GSONよりも冗長になる。
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になる。
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
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のモデルクラスに読み込む
ポイントとなるコードは以下のようになる
ObjectMapper mapper = new ObjectMapper();
Model model = mapper.readValue(json, Model.class);
コード全体は以下のようになる
■ 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化する。
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(model);
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を出力できた
{"person":{"firstName":"ジョン","lastName":"ドゥ","address":"ニューヨーク","pets":[{"type":"犬","name":"ジョリー"},{"type":"猫","name":"グリザベラ"},{"type":"魚","name":"ニモ"}]}}
(5) Jacksonを使って、JSONを整形(Pretty Printing)して出力
このようにすると、JSONがインデントされキレイにフォーマットされて出てくる
ObjectMapper mapper2 = new ObjectMapper();
String prettyJson = mapper2.writerWithDefaultPrettyPrinter().writeValueAsString(model);
System.out.println(prettyJson);
実行結果
{
"person" : {
"firstName" : "ジョン",
"lastName" : "ドゥ",
"address" : "ニューヨーク",
"pets" : [ {
"type" : "犬",
"name" : "ジョリー"
}, {
"type" : "猫",
"name" : "グリザベラ"
}, {
"type" : "魚",
"name" : "ニモ"
} ]
}
}