【Java】Jacksonを使ったJSONの解析(導入とデコード)

B!

概要

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;
}

上記でのポイントは

  1. JSONのキー名をインスタンス変数名と合わせる
  2. JSONの型をインスタンス変数の型と合わせる
  3. 日時はDate型にマッピングできる。フォーマットは @JsonFormatアノテーションで指定する。
  4. 配列はListにマッピングできる
  5. インスタンス変数ごとに 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文字列に変換

長くなりましたので、次回に紹介します。

スポンサーリンク
最新の記事はこちらから