Jackson は、Java オブジェクトをさまざまなテキスト形式にシリアル化/逆シリアル化するための人気のあるライブラリです。ObjectMapperクラスはライブラリが JSON 形式を操作する主な方法です。他の形式については、その子孫 ( XmlMapperYAMLMapper )があります。継承のおかげで、単一のインターフェイスを通じて、すべての形式を一貫した方法で操作できます。

jar ファイルをダウンロードする

例を検討する前に、Jackson jar ファイルをダウンロードし、IntelliJ IDEA のプロジェクトに接続する必要があります。jackson-databindの例を使用して、必要なファイルを検索する方法を見てみましょう。

  1. Maven リポジトリWeb サイトに移動します。

  2. 検索ボックスに「jackson-databind 」と入力します。次の内容が得られます。

  3. 最初の検索結果が興味のあるものです。リンクをクリックしてください。

  4. プロジェクト内の他のコンポーネントとの互換性を確保するために、ライブラリの特定のバージョンが必要になる場合があります。最新バージョンは動作するはずです (このレッスンの作成時点では、2.13.2.2 です)。リンクに従ってください。

  5. 開いたページに「バンドル」リンクが必要です。

  6. このリンクを使用して jar ファイルをダウンロードします。

同様の手順に従って、残りの必要な jar ファイルを見つけてダウンロードできます。

必要なファイルをすべてダウンロードしたら、それらを IntelliJ IDEA のプロジェクトに接続します。

  1. プロジェクト設定を開きます ( Ctrl+Alt+Shift+Sキーの組み合わせで実行できます)。

  2. 「ライブラリ」に移動します。

  3. + を押してから「Java」を押します。ダウンロードしたファイルをすべて選択します。最終的には次のようになります。

  4. これで準備作業は終了です。ここで、 ObjectMapper を実際に試してみましょう。

JSONへのシリアル化

まず、オブジェクトを JSON にシリアル化しましょう。


import com.fasterxml.jackson.databind.ObjectMapper;
 
class Book {
	public String title;
	public String author;
	public int pages;
}
 
public class Solution {
	public static void main(String[] args) throws Exception {
    	Book book = new Book();
    	book.title = "Good Omens";
    	book.author = "Pratchett T., Gaiman N.";
    	book.pages = 383;
 
    	ObjectMapper mapper = new ObjectMapper();
    	String jsonBook = mapper.writeValueAsString(book);
    	System.out.println(jsonBook);
	}
}

mainを実行すると、次の出力が得られます。

{"title":"Good Omens","author":"Pratchett T.、Gaiman N.","pages":383}

ObjectMapperは多くの詳細設定があります。そのうちの 1 つを使用して、JSON 文字列を読みやすくしてみましょう。を作成した後、オブジェクトマッパーオブジェクトの場合は、次のステートメントを実行します。

Mapper.enable(SerializationFeature.INDENT_OUTPUT);

出力内の情報は変わりませんが、インデントと改行が追加されています。

{
  "タイトル" : "グッド オーメンズ"、
  "著者" : "プラチェット T.、ゲイマン N."、
 "ページ数" : 383
}

JSONからの逆シリアル化

次に、逆のアクションを実行してみましょう。文字列をオブジェクトに逆シリアル化します。プログラムが何を行っているかを確認できるようにするには、BookクラスのtoStringメソッドをオーバーライドしましょう。


@Override
public String toString() {
	return "Book{" +
        	"title='" + title + '\'' +
        	", author='" + author + '\'' +
        	", pages=" + pages +
        	'}';
}

そして、 mainメソッドで次のことを実行します。


public static void main(String[] args) throws Exception {
	String jsonString = "{\"title\":\"Good Omens\",\"author\":\"Pratchett T., Gaiman N.\",\"pages\":383}";
	Book book = new ObjectMapper().readValue(jsonString, Book.class);
	System.out.println(book);
}

出力:

本{title='グッド・オーメンズ'、著者='プラチェット・T.、ゲイマン・N.'、ページ=383}

readValueメソッドはオーバーロードされています。このメソッドに、ファイル、リンク、さまざまな入力ストリームなどを受け取る多くのバリエーションがあります。簡単にするために、この例では JSON 文字列を受け入れるバリアントを使用しています。

上で述べたように、ObjectMapperには多くの設定があります。そのうちのいくつかを見てみましょう。

未知のプロパティを無視する

JSON 文字列にBookクラスに存在しないプロパティがある状況を考えてみましょう。


public static void main(String[] args) throws Exception {
	String jsonString = """
        	{
          	"title" : "Good Omens",
          	"author" : "Pratchett T., Gaiman N.",
          	"pages" : 383,
          	"unknown property" : 42
        	}""";
	ObjectMapper mapper = new ObjectMapper();
	Book book = mapper.readValue(jsonString, Book.class);
	System.out.println(book);
}

このコードを実行すると、UnrecognizedPropertyExceptionが発生します。これはデフォルトの動作ですが、変更できます。


ObjectMapper mapper =
new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

を作成するときは、オブジェクトマッパーオブジェクトの場合は、 configureメソッドを使用して、対応する設定をfalseに設定します。configureメソッドは、呼び出されたオブジェクトを変更してから、その同じオブジェクトを返すため、この呼び出しを別の方法で行うことができます。


ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

機能の点では、この表記は前の表記とまったく同じです。

ここでmainメソッドを実行すると、逆シリアル化は成功し、不明なプロパティは無視されます。

便利な注釈

Jackson は、シリアル化プロセスをあらゆる種類の方法でカスタマイズできるようにするいくつかのアノテーションを提供します。最も便利なものをいくつか見てみましょう。

@JsonIgnore — このアノテーションは、シリアル化/逆シリアル化中に無視される必要がある要素の上に配置されます。


class Book {
	public String title;
	@JsonIgnore
	public String author;
	public int pages;
}

ここで、著者フィールドは、シリアル化中に結果の JSON に含まれません。逆シリアル化すると、著者JSON の値が異なる場合でも、フィールドはデフォルト値 (null) を取得します。

@JsonFormat — このアノテーションを使用すると、シリアル化されたデータの形式を設定できます。もう 1 つのフィールドDate をBookクラスに追加しましょう。


class Book {
	public String title;
	public String author;
	public int pages;
	public Date createdDate = new Date();
}

シリアル化後、次の JSON を取得します。

 {
  "タイトル" : "グッド オーメンズ"、
  "著者" : "プラチェット T.、ゲイマン N."、
  "ページ数" : 383、
  "作成日" : 1649330880788
}

ご覧のとおり、日付は数値としてシリアル化されています。注釈を追加し、形式を設定します。


class Book {
	public String title;
	public String author;
	public int pages;
	@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
	public Date createdDate = new Date();
}

シリアル化の結果は次のようになります。

{
  "title" : "Good Omens",
  "author" : "Pratchett T.、Gaiman N."、
  "pages" : 383、
  "createdDate" : "2022-04-07"
}

@JsonProperty — このアノテーションを使用すると、シリアル化されたフィールドを表すプロパティの名前を変更できます。このアノテーションを使用してメソッドをマークすることもできます。そうすると、戻り値はシリアル化中に JSON プロパティに変換されます。


class Book {
	@JsonProperty("name")
	public String title;
	public String author;
	public int pages;
 
	@JsonProperty("quotedTitle")
	public String getQuotedTitle() {
    	    return "\"" + title + "\"";
	}
}

シリアル化の結果:

{
  "著者" : "プラチェット T.、ゲイマン N."、
  "ページ" : 383、
  "名前" : "グッド オーメンズ"、
  "quotedTitle" : "\"グッド オーメンズ\""
}

@JsonInclude — このアノテーションを使用すると、フィールドをシリアル化するために満たさなければならない条件を指定できます。個々のフィールドまたはクラス全体に適用できます。まず、初期化されていないフィールドを持つオブジェクトをシリアル化してみましょう。


public class Solution {
	public static void main(String[] args) throws Exception {
    		Book book = new Book();

    		ObjectMapper mapper = new ObjectMapper();
    		mapper.enable(SerializationFeature.INDENT_OUTPUT);
    		String jsonBook = mapper.writeValueAsString(book);
    		System.out.println(jsonBook);
	}
}

シリアル化の結果:

{
  "タイトル" : null、
  "著者" : null、
  "ページ" : 0
}

そして、注釈を追加すると、次のようになります。


@JsonInclude(JsonInclude.Include.NON_NULL)
class Book {
	public String title;
	public String author;
	public int pages;
}

すると、次の結果が得られます。

{
  "ページ" : 0
}

nullのフィールドはシリアル化されなくなりました。

@JsonPropertyOrder — このアノテーションを使用すると、フィールドがシリアル化される順序を設定できます。


@JsonPropertyOrder({"author", "title", "pages"})
class Book {
	public String title;
	public String author;
	public int pages;
}

シリアル化の結果:

{
  "著者" : "プラチェット T.、ゲイマン N."、
  "タイトル" : "グッド オーメンズ"、
  "ページ数" : 383
}

ここでは、注釈の使用方法を覚えておいてください。このモジュールの最後では、それらについてさらに詳しくなり、独自の注釈も作成できるようになります。

XML でのシリアル化と逆シリアル化

XML にシリアル化する必要がある場合は、すべて同じ設定と注釈を使用できます。唯一の違いは実装です。マッパーオブジェクト:


public static void main(String[] args) throws Exception {
	Book book = new Book();
	book.title = "Good Omens";
	book.author = "Pratchett T., Gaiman N.";
	book.pages = 383;
 
	ObjectMapper mapper = new XmlMapper();
	mapper.enable(SerializationFeature.INDENT_OUTPUT);
	String xmlBook = mapper.writeValueAsString(book);
	System.out.println(xmlBook);
}

出力:

 <本>
  <title>グッド・オーメンズ</title>
  <author>Pratchett T.、Gaiman N.</author>
  <pages>383</pages>
</Book>

XML の逆シリアル化:


public static void main(String[] args) throws Exception {
   String xmlString = """
            <Book>
             <title>Good Omens</title>
             <author>Pratchett T., Gaiman N.</author>
             <pages>383</pages>
           </Book>""";
   ObjectMapper mapper = new XmlMapper();
   Book book = mapper.readValue(xmlString, Book.class);
   System.out.println(book);
}

YAML でのシリアル化と逆シリアル化

XML を処理するのと同じ方法で YAML を処理します。


public static void main(String[] args) throws Exception {
	Book book = new Book();
	book.title = "Good Omens";
	book.author = "Pratchett T., Gaiman N.";
	book.pages = 383;
 
	ObjectMapper mapper = new YAMLMapper();
	mapper.enable(SerializationFeature.INDENT_OUTPUT);
	String yamlBook = mapper.writeValueAsString(book);
	System.out.println(yamlBook);
}

出力:

---
タイトル: 「グッド オーメンズ」
著者: 「プラチェット T.、ゲイマン N.」
ページ: 383

YAML の逆シリアル化:


public static void main(String[] args) throws Exception {
   String yamlString = """
           ---
           title: "Good Omens"
           author: "Pratchett T., Gaiman N."
           pages: 383""";
   ObjectMapper mapper = new YAMLMapper();
   Book book = mapper.readValue(yamlString, Book.class);
   System.out.println(book);
}