概要
前回の記事に引き続き、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型で代用する方法を調べたいと思います。