概要
前回の記事に引き続き、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;
}
上記でのポイントは
- JSONのキー名をインスタンス変数名と合わせる
- JSONの型をインスタンス変数の型と合わせる
- 日時はDate型にマッピングできる。フォーマットは @JsonFormatアノテーションで指定する。
- 配列はListにマッピングできる
- インスタンス変数ごとに 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型で代用する方法を調べたいと思います。