【Java】Jacksonを使ったJSONの解析(エンコード、文字列化)

概要

前回の記事に引き続き、Jacksonを使ったJSONの解析方法について紹介していきます。今回は、JavaオブジェクトをJSON文字列に変換する方法です。1つのシステム内で複数の WebAPI を自作していると、Javaオブジェクトは共通なんだけど、あるAPIには出力したいけど別のAPIには出力したくないフィールドがあることがあります。その解決方法についても説明していきます。

スポンサーリンク

基本的な使い方

下記のような POJO を JSON文字列化したいとします。前回の記事にもありますが、Lombokを使用して Getter / Setter を書いていません。

import java.util.Date;
import java.util.List;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.ObjectMapper;

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;
}
import lombok.Data;

@Data
public class Contact {
	private String email;
	private String tel;
}

上記でのポイントは

  1. JSONのキー名をインスタンス変数名と合わせる
  2. JSONの型をインスタンス変数の型と合わせる
  3. 日時はDate型にマッピングできる。フォーマットは @JsonFormatアノテーションで指定する。
  4. 配列はListにマッピングできる
  5. インスタンス変数ごとに getter / setter を実装する

上記の 5番目に getter / setter を実装とありますが、ここでLombokの出番となります。代わりに、クラスに @Data アノテーションを付けるだけでOKです。

次に変換処理部分です。

import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import com.fasterxml.jackson.databind.ObjectMapper;

public class PersonTest2 {
	public static void main(String[] args) throws Exception {
		Person person = new Person();
		
		person.setName("山田太郎");
		person.setAge(30);
		
		Calendar birthDay = Calendar.getInstance();
		birthDay.set(1988, 3, 24);
		person.setBirthday(birthDay.getTime());
		
		person.setHobby(Arrays.asList("読書", "ゴルフ"));
		
		Contact contact = new Contact();
		contact.setEmail("yamada@example.com");
		contact.setTel("090-xxxx-xxxx");
		person.setContact(contact);
		
		ObjectMapper mapper = new ObjectMapper();
		String json = mapper.writeValueAsString(person);
		System.out.println(json);
	}
}

ObjectMapper に POJOのインスタンスを渡せば、文字列として取得できます。

出力したくないフィールドがある場合

JSON文字列に出力したくないフィールドがある場合には @JsonIgnore アノテーションを付けます。
下記の例では、contact を出力しません。

import java.util.Date;
import java.util.List;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.ObjectMapper;

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;
	@JsonIgnore
	private Contact contact;
}

場合によっては出力したくないフィールドがある場合

Jacksonに用意されている JsonView という機能を使います。まずはViewクラスを用途ごとに作成しておきます。

/**
 * JsonView定義
 */
public class Views {
	/** API1用 View */
	public static class View1 {
	}
	/** API2用 View */
	public static class View2 extends View1 {
	}
}

ここでポイントなのは、2点です。

  • static なクラスであること。中身は必要ない。
  • View1 を継承して View2 を作っていること

View2 に出力されるフィールドには、View1 に定義したフィールドを含むようになるので、View2 には増分だけを指定することができます。

下記のように、View は @JsonView を使って指定します。name と age と birthday を View1 に指定しました。hobby と contact は View2 に指定しました。

import java.util.Date;
import java.util.List;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonView;

import lombok.Data;

@JsonIgnoreProperties(ignoreUnknown=true)
@Data
public class Person {
	@JsonView(Views.View1.class)
	private String name;

	@JsonView(Views.View1.class)
	private int age;

	@JsonView(Views.View1.class)
	@JsonFormat(pattern = "yyyy年MM月dd日", timezone = "Asia/Tokyo")
	private Date birthday;

	@JsonView(Views.View2.class)
	private List<String> hobby;
	
	@JsonView(Views.View2.class)
	private Contact contact;
}

View を使って JSON文字列を作成するには、writerWithView() を挟みます。

Person person = new Person();
		
person.setName("山田太郎");
person.setAge(30);
		
Calendar birthDay = Calendar.getInstance();
birthDay.set(1988, 3, 24);
person.setBirthday(birthDay.getTime());
		
person.setHobby(Arrays.asList("読書", "ゴルフ"));
		
Contact contact = new Contact();
contact.setEmail("yamada@example.com");
contact.setTel("090-xxxx-xxxx");
person.setContact(contact);
		
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writerWithView(Views.View1.class).writeValueAsString(person);
System.out.println(json); // name, age, birthday のみ含む JSON
Person person = new Person();
		
person.setName("山田太郎");
person.setAge(30);
		
Calendar birthDay = Calendar.getInstance();
birthDay.set(1988, 3, 24);
person.setBirthday(birthDay.getTime());
		
person.setHobby(Arrays.asList("読書", "ゴルフ"));
		
Contact contact = new Contact();
contact.setEmail("yamada@example.com");
contact.setTel("090-xxxx-xxxx");
person.setContact(contact);
		
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writerWithView(Views.View2.class).writeValueAsString(person);
System.out.println(json); // name, age, birthday, hobby, contact を含む JSON

次の課題

Javaオブジェクトを定義せず、Map型で代用する方法を調べたいと思います。

スポンサーリンク
関連キーワード
Javaの関連記事
  • 【TwitterAPI】POST statuses/update APIの使い方( Java で ツイートbot)
  • 【TwitterAPI】Search API の使い方(Java編)
  • 【Java】Jacksonを使ったJSONの解析(エンコード、文字列化)
  • Jacksonで文字列をオブジェクトへ変換
    【Java】Jacksonを使ったJSONの解析(導入とデコード)
  • JavaでHTTPクライアント
    【Java】OkHttp で HTTP クライアントを作成する方法
おすすめの記事