このページの内容
概要
JSON文字列とJavaオブジェクトとの相互変換を行うライブラリはいくつかありますが、今回はJacksonを使った方法を紹介します。Javaオブジェクト側には getter/setter が必要になるのですが、Lombokを使えばさらにシンプルなソースコードになります。
Jacksonの導入
使っている環境に合わせて、下記のようにします。バージョンは任意のものを使ってください。
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.9.6</version> </dependency>
dependencies { compile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.9.6' }
Lombokの導入
Lombokを使うと、お決まりの getter / setter / toString / equals などのメソッドを自動的に生成してコンパイルしてくれるので、ソースコード量が減って見通しが良くなります。コンパイル時にのみ必要なので、pom.xml に記載する際には、スコープは provided(gradleの場合は、compileOnlyとなります。)また、pom.xml(build.gradle)への記載に加えて、IDEへのインストールが必要です。
IDEへのインストール
まずは https://projectlombok.org/download のページからJarファイルをダウンロードします。このJarファイルは実行可能Jarになっていますので、ダブルクリックするとインストーラー画面が起動します。インストール画面で、お使いのIDE(eclipse.exe、sts.exe、など)の場所を指定して、インストールします。
プロジェクトへ導入
使っている環境に合わせて、下記のようにします。バージョンは任意のものを使ってください。
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.4</version> <scope>provided</scope> </dependency>
dependencies { compileOnly "org.projectlombok:lombok:1.18.4" }
dependencies { provided "org.projectlombok:lombok:1.18.4" }
JSON文字列をJavaオブジェクトに変換
基本的な使い方
下記のようなJSON文字列をJavaオブジェクトに変換したいとします。
{ "name": "山田太郎", "age": 33, "birthday": "1988-03-24", "hobby": ["読書", "ゴルフ"] }
変換後のPOJOを準備します。
import java.util.Date; import java.util.List; import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Data; @Data public class Person { private String name; private int age; @JsonFormat(pattern = "yyyy-MM-dd", timezone = "Asia/Tokyo") private Date birthday; private List<String> hobby; }
上記でのポイントは
- JSONのキー名をインスタンス変数名と合わせる
- JSONの型をインスタンス変数の型と合わせる
- 日時はDate型にマッピングできる。フォーマットは @JsonFormatアノテーションで指定する。
- 配列はListにマッピングできる
- インスタンス変数ごとに getter / setter を実装する
上記の 5番目に getter / setter を実装とありますが、ここでLombokの出番となります。代わりに、クラスに @Data アノテーションを付けるだけでOKです。
次に、変換処理部分です。
import java.util.Date; import java.util.List; import com.fasterxml.jackson.databind.ObjectMapper; public class PersonTest { public static void main(String[] args) throws Exception { String json = "{\"name\":\"山田太郎\",\"age\":30,\"birthday\":\"1988-03-24\",\"hobby\":[\"読書\",\"ゴルフ\"]}"; ObjectMapper mapper = new ObjectMapper(); Person person = mapper.readValue(json, Person.class); // Lombok が getter や toString を補ってくれているので使える System.out.println(person.getName()); System.out.println(person.getBirthday()); System.out.println(person.getHobby()); System.out.println(person); } }
ObjectMapper に JSON文字列とPOJOのClassを渡せば、インスタンスとして取得できます。
このインスタンスは、Lombokによって getter / setter / toString / equals などが実装されているので使うことができます。
オブジェクトがネストしているとき
次に下記のように、オブジェクトがネストしている場合を考えます。(contactの部分)
{ "name": "山田太郎", "age": 33, "birthday": "1988-03-24", "hobby": ["読書", "ゴルフ"], "contact" : { "email" : "yamada@example.com", "tel": "090-xxxx-xxxx" } }
ネストしている部分のPOJOを同様に準備します。
import lombok.Data; @Data public class Contact { private String email; private String tel; }
それをインスタンス変数に追加しておくだけです。
import java.util.Date; import java.util.List; import lombok.Data; @Data public class Person { private String name; private int age; @JsonFormat(pattern = "yyyy-MM-dd", timezone = "Asia/Tokyo") private Date birthday; private List<String> hobby; private Contact contact; }
JSON文字列とPOJOのキーの数が一致しないとき
下記のようなケースで、JSON文字列とPOJOのキーの数が一致しないことが出てきます。
- JSON文字列側には存在するキーを、処理に必要がないためにPOJO側には作りたくない
- JSON文字列側には存在しないキーを、処理に必要なためにPOJO側に作りたい
- JSONを返すAPIの仕様として、キーを返してくれる場合と返してくれない場合がある
キーが一致しない場合、例外が発生してしまいうまく変換できません。
Exception in thread "main" com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "hoge"
そういった場合は、POJO側のクラスに @JsonIgnoreProperties(ignoreUnknown=true) アノテーションを付けます。
import java.util.Date; import java.util.List; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import lombok.Data; @JsonIgnoreProperties(ignoreUnknown=true) @Data public class Person { private String name; private int age; @JsonFormat(pattern = "yyyy-MM-dd", timezone = "Asia/Tokyo") private Date birthday; private List<String> hobby; private Contact contact; }
JavaオブジェクトをJSON文字列に変換
長くなりましたので、次回に紹介します。