Javaについて徹底解説!

JavaでJSONを楽々読み書きしよう! Jacksonの基本を解説

大石 英人

大石 英人

開発エンジニア/Java20年/Java GOLD/リーダー/ボールド歴2年

プログラミングをしていると“JSON”という言葉をよく見かけませんか?

JSONって一体何? そもそもどう読むの? じぇーえすおーえぬ?」という方もいらっしゃるでしょう。実は私も、結構最近までそんな人でした。うわー、恥ずかしい

JSON(ジェイソン、JavaScript Object Notation)とは、HTMLXMLCSVのようなデータ形式の一つです。

プログラムでJSONを使えると、とても色々なことができるようになり、世界が大きく広がります。なぜかというと、例えばTwitterFacebookGoogleなどのWEBサービスとはJSONでやりとりするからです。

つまり、JSONが分かれば、世の中にあるWEBサービスの色々な機能を自分で使えるようになるのです!!そんな自分を想像してみると、とてもワクワクしませんか? イケてるし、格好いいなぁと思いませんか?

この記事では、JSONの簡単な説明と、JavaからJSONを使うにはどうすればいいのかを、JSONの初心者向けにお伝えします!!

※この記事のサンプルは、Java 10の環境で動作確認しています。


1.JSONとはどんなものだろう

1-1.JSONはデータ構造を見やすく表現できるデータ形式

JSON(ジェイソン、JavaScript Object Notation)とは、データ形式の一つです。JSONは「構造」を持ったデータを、見やすい形で表現するのが得意です。TwitterやFacebookGoogleなどのインターネット上のWEBサービスや、企業システム間でのデータのやり取りで大変よく使われます。

★Introduction to Tweet JSON(Twitter)

https://developer.twitter.com/en/docs/tweets/data-dictionary/overview/intro-to-tweet-json.html

★Using the Graph API(Facebook)

https://developers.facebook.com/docs/graph-api/using-graph-api

★Google Maps Platform – Geo-location API(Google)

https://cloud.google.com/maps-platform/?hl=ja

では、JSONのいいところを挙げてみます。

  • 構文が簡単なので、人間がパッと見てもデータの構造がすぐわかる
  • テキストデータなので、データのやり取りが大変やりやすい
  • JSONを使うためのライブラリはたくさんあり、様々なプログラミング言語で簡単に使える

名前にある“JavaScript”から想像できるかもしれませんが、JavaScriptでは実に簡単に使えてしまいます。でも、JavaからJSONを使うためのライブラリももちろんありますので、ご安心ください。

1-2.JSONとJavaのクラスを見比べてみよう

さてJSONとは何ぞやな話は終わりにして、さっそくJSONの実物を見てみましょう。

これは一つのTweetを表現しているつもりのJSONです。Twitterの開発者向けドキュメントから拝借して、内容を少々簡略化したものです。なんとなく、どういうものか分かるでしょうか。

{
	"created_at":"Thu Apr 06 15:24:15 +0000 2017",
	"id": 850006245121695744,
	"text": "ツイート",
}

JSONは、Javaのクラス宣言と似ているところも多いです。

似たようなJavaのクラスとそのインスタンスを作ってみて、ちょっと見比べてみましょう。

public class Tweet {
	public String created_at;
	public long id;
	public String text;
}
class TweetSample {
	public static void main(String[] args) {
		Tweet t = new Tweet();
		t.created_at = "Thu Apr 06 15:24:15 +0000 2017";
		t.id = 850006245121695744L;
		t.text = "ツイート";
	}
}

JSONとJavaの二つを見比べてみると、どういう関係がありそうか、うっすらと見えてきませんか?

JSONの「{}」でくくられた部分がJavaで言うインスタンスで、「“XXX” : YYY」が、Javaでのインスタンスフィールドの名前と値のことかなと察しがついたかと思います。

ここで、“XXX”のことをプロパティの「キー(key)」、YYYをプロパティの「値(value)」と一般的には呼びますので、ぜひ覚えておきましょう。

つまり、JSONとはオブジェクトの構造やプロパティが持つ値を、ごく素直にテキストで表現したものなのです。ですので、JSONを使うということは、JSONの文字列を読み込んで、何かの処理をして、JSONの文字列として出力することなのです。


2.JavaのJSONライブラリを活用しよう

JavaでJSONを使うには、既にあるAPIやライブラリを活用しましょう。

Javaでの有名どころなJSONライブラリとしては、以下のものが挙げられます。これらのライブラリを使えば、JSONの読み書きと編集がJavaでも簡単にできてしまうのです。

以下、この記事ではJacksonを使ったJavaプログラムの例をお伝えします。

Jacksonは広く使われているライブラリで、使い方・活用方法などの情報もインターネットで豊富に入手できます。

バージョンアップもずっと続いていますので、これからもどんどん使いやすくなることが期待できますよ。

ちなみに、AndroidのプログラムではGsonが広く使われていますし、JSON in Javaもとても良く使われています。ですので、いくつかのライブラリの使い方を知っておくのもいいでしょう。


3.Jacksonの使い方の基本

JacksonでJSONを読み書きするには、大きく分けると以下の二つの方法があります。

  1. JSONのデータ構造と同じクラスを作り、JSONと紐付けて読み書きする
  2. JsonNode/ObjectNodeを使う方法:JSONのデータ構造を扱えるクラスで読み書きする

直感的にプログラミングできるのは1.です。基本的にはこちらをお勧めします。でも、2.のやり方も知っていると便利でしょう。複雑な構造を持つJSONだと、対応するクラスを作ることそのものが大変な場合もあるからです。

この章では、Jacksonを使うためのプロジェクトのセットアップと、これら二つの方法でのプログラミングの仕方を、簡単にご紹介します。

3-1.Jacksonを使えるようにしよう!

JacksonはJavaの標準APIには含まれていませんので、あなたのプログラムから使うには少しセットアップが必要となります。

セットアップには、MavenGradleなどのプロジェクト管理ツールを使う方法と、jarファイルを使う方法の二種類があります。MavenやGradleについて良くわからない場合は、まずはjarファイルを使う方法でやってみましょう!!

3-1-1.MavenかGradleを使っている場合

プロジェクトでMavenを使っている場合は、pom.xmlへ依存アーティファクトとして以下を足しましょう。バージョン2.9.7は、2018/12時点でMavenのリポジトリにある最新バージョンです。基本的には、使おうとしている時の最新バージョンで問題ないでしょう。

なお、本当の意味でJacksonの最低限の機能を使うにはjackson-coreだけがあれば良いのですが、それだけだとプログラミングはなかなか難しいです。jackson-databindとjackson-annotationがあれば、色々と便利なクラスが使えるので、一緒に使うのが普通です。

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.9.7</version>
</dependency>

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.7</version>
</dependency>

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>2.9.7</version>
</dependency>

Gradleを使っている場合は、build.gradleに以下を足しましょう。

compile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.9.7'
compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.9.7'
compile group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version: '2.9.7'

3-1-2.jarファイルを使う場合

まずは、以下のURLから、3つのjar(jackson-core-2.x.x.jarjackson-databind-2.x.x.jarjackson-annotations-2.x.x.jar)をダウンロードしましょう。

http://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-core/

→ jackson-core-2.9.8.jar

http://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-databind/

→ jackson-databind-2.9.8.jar

http://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-annotations/

→ jackson-annotations-2.9.8.jar

バージョンは最も新しいもので問題ありませんが、3種類のjarのバージョンは合わせておきましょう。2018/12時点でダウンロードできる最も新しいバージョンは2.9.8です。

Eclipseからこれらのjarの中にあるクラスを使うためには、プロジェクトのクラスパスにjarを含めなければなりません。具体的には、以下のように設定しましょう。皆さんの環境に合わせて、読み替えいただく必要がある箇所があるかもしれませんね。

Jacksonセットアップ手順1

 

Jacksonセットアップ手順2

Jacksonセットアップ手順3

Jacksonセットアップ手順4

3-2.JSONとクラスを紐付けて使う場合

3-2-1.JSONをJavaのインスタンスに変換する

Jacksonを使うときは、ObjectMapper.readValueを使うと、直感的にJSONJavaクラスのインスタンスにできます。

まず、JSONで持っているプロパティと同じ名前のフィールドを持つクラスを作りましょう。クラスのフィールドの型は、JSONのプロパティに設定されてるものと同じ型にしましょう。クラス名はお好きなものを付けて大丈夫です。

{
	"created_at":"Thu Apr 06 15:24:15 +0000 2017",
	"id": 850006245121695744,
	"text": "ツイート",
}
public class Tweet {
	public String created_at;
	public long id;
	public String text;
}

その後、JSON文字列のStringとクラスを引数にして、ObjectMapper.readValueを実行しましょう。戻り値は、JSON文字列を読み込んだ結果の、Javaクラスのインスタンスです。

この例では、先述したTweetクラスを使ってみます。

import com.fasterxml.jackson.databind.ObjectMapper;

public class JsonSample2 {
	public static void main(String[] args) throws Exception {
		String json = "{"
				+ "\"created_at\":\"Thu Apr 06 15:24:15 +0000 2017\", "
				+ "\"id\": 850006245121695744, "
				+ "\"text\": \"ツイート\""
				+ "}";

		ObjectMapper mapper = new ObjectMapper();
		Tweet t = mapper.readValue(json, Tweet.class);

		System.out.println(t.created_at); // → "Thu Apr 06 15:24:15 +0000 2017"
		System.out.println(t.id); // → 850006245121695744
		System.out.println(t.text); // → "ツイート"
	}
}

JSONのプロパティと同じ名前を持つJavaクラスのフィールドに、値が設定されているのが分かると思います。

これがJSON文字列をJavaクラスのインスタンスへ変換する際の基本形です。

3-2-2.JavaのインスタンスをJSONに変換する

JavaクラスのインスタンスをJSON文字列とする時は、ObjectMapper.writeValueAsStringを使います。

import com.fasterxml.jackson.databind.ObjectMapper;

public class JsonSample3 {
	public static void main(String[] args) throws Exception {
		Tweet t = new Tweet();
		t.created_at = "Thu Apr 06 15:24:15 +0000 2017";
		t.id = 850006245121695744L;
		t.text = "ツイート";

		ObjectMapper mapper = new ObjectMapper();
		String json = mapper.writeValueAsString(t);

		System.out.println(json); // → {"created_at":"Thu Apr 06 15:24:15 +0000 2017","id":850006245121695744,"text":"ツイート"}
	}
}
// JSONへの変換結果
{"created_at":"Thu Apr 06 15:24:15 +0000 2017","id":850006245121695744,"text":"ツイート"}

クラスのフィールドが、JSONのプロパティになっています。このように、クラスとJSONを紐付けられるのですね。

前項での読み込みのやり方と合わせ、この章の冒頭でお伝えした「Jacksonを使うとJSONを直感的に使える」ということが、お分かりいただけたでしょうか。

3-3.JsonNode/ObjectNodeを使う場合

3-3-1.JSONをJsonNodeに変換する

JSONと紐付けるクラスを作って使う他に、Jacksonが用意しているクラスのJsonNodeObjectNodeを使っても、JSONJavaから利用できます。

JsonNodeは、JSONを読み取った結果を表現しているクラスです。

JsonNodeを使う場合は、ObjectMapper.readTreeを使って、JSON文字列からJsonNodeを作り出します。

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

public class JsonSample4 {
	public static void main(String[] args) throws Exception {
		String json = "{"
				+ "\"created_at\":\"Thu Apr 06 15:24:15 +0000 2017\", "
				+ "\"id\": 850006245121695744, "
				+ "\"text\": \"ツイート\""
				+ "}";

		ObjectMapper mapper = new ObjectMapper();
		JsonNode node = mapper.readTree(json);

		System.out.println(node.get("created_at").textValue()); // → "Thu Apr 06 15:24:15 +0000 2017"
		System.out.println(node.get("id").longValue()); // → 850006245121695744
		System.out.println(node.get("text").textValue()); // → "ツイート"
	}
}

例にあるとおり、JsonNode.get(String)を実行すると、そのプロパティを表すJsonNodeを取得できます。

さらにプロパティの値を取得するには、JsonNode.textValue/booleanValue/intValueなどの、~Valueというメソッドを呼び出します。

// ~Valueメソッドの一覧(Jackson 2.9 APIより)
BigInteger bigIntegerValue()
byte[] binaryValue()
boolean booleanValue()
BigDecimal decimalValue()
double doubleValue()
float floatValue()
int intValue()
long longValue()
Number numberValue()
short shortValue()
String textValue()

さて、見てのとおり、クラスと紐付けるよりもプログラムは長くなってしまいますし、少々直感的ではなくなります。

ですが、専用のクラスを事前に用意しなくても、どのような構造のJSONであっても読み込めるのが利点です。

3-3-2.ObjectNodeからJSONに変換する

JSONを作る場合は、ObjectNodeを使います。

ObjectNodeは、ObjectMapper.createObjectNodeを使って生成します。

生成したObjectNodeに、キーと値のペアをputすればJSONを編集できます。

編集後のObjectNodeは、ObjectMapper.writeValueAsStringで、JSON文字列に変換できます。

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;

public class JsonSample5 {
	public static void main(String[] args) throws Exception {
		ObjectMapper mapper = new ObjectMapper();

		ObjectNode node = mapper.createObjectNode();
		node.put("created_at", "Thu Apr 06 15:24:15 +0000 2017");
		node.put("id", 850006245121695744L);
		node.put("text", "ツイート");

		String json = mapper.writeValueAsString(node);

		System.out.println(json); // → {"created_at":"Thu Apr 06 15:24:15 +0000 2017","id":850006245121695744,"text":"ツイート"}
	}
}

ObjectNode.putには、値の種類(String/boolean/int/long/double)に応じて、オーバーロードされたメソッドが用意されています。

ObjectやMapなどをputするには、putObject/putArray/putPOJO/putNullなどがありますので、使い分けましょう。

3-3-3.JsonNodeからObjectNodeに変換して編集する

JsonNodeは読み取り専用なので、読み取ったJSONの値を変更する操作はできません。でも、読み取ったJSONをベースに、一部だけ値を変更したり、プロパティを追加できたりすれば、楽が出来ますよね。

その場合は、JsonNodeObjectNodeに変換してしまいましょう。JsonNode.deepCopyを使ってObjectNodeに変換すれば、変換後のObjectNodeで値を変更したり、プロパティを追加できます。

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;

public class JsonSample6 {
	public static void main(String[] args) throws Exception {
		String json = "{"
				+ "\"created_at\":\"Thu Apr 06 15:24:15 +0000 2017\", "
				+ "\"id\": 850006245121695744, "
				+ "\"text\": \"ツイート\""
				+ "}";

		ObjectMapper mapper = new ObjectMapper();
		JsonNode jnode = mapper.readTree(json);
		ObjectNode onode = jnode.deepCopy();

		onode.put("created_at", "2018年12月19日");
		onode.put("id", 12345);
		onode.put("text", "Tweet!!");
		onode.put("something", "anything");

		String json2 = mapper.writeValueAsString(onode);

		System.out.println(json2); // → {"created_at":"2018年12月19日","id":12345,"text":"Tweet!!","something":"anything"}
	}
}
// 編集後のJSON
{"created_at":"2018年12月19日","id":12345,"text":"Tweet!!","something":"anything"}

4.【参考】Jackson関連リソースリンク集

公式プロジェクト WEBページ

公式ドキュメント

Stack OverflowのJacksonに関するQ&A


5.まとめ

この記事では、JSONとはどんなものか、JSONJavaから扱うためのライブラリにはどんなものがあるか、そのライブラリの一つJacksonの使い方について基本をお伝えしました。

JSONとは、データ構造とプロパティの値を、人間にとって見やすく記述できるデータ形式です。

JacksonのObjectMapperを使えば、JSONJavaのクラスを紐付けて、直感的にJSONの読み書きができます。Javaのクラスを紐付けない場合は、JsonNodeObjectNodeを使えばJSONを読み書きできます。この二つのやり方は、プログラムでの用途に応じて使い分けましょう。

なお、今回お伝えしたのはJacksonが本来持つ実力の、ほんの一部です。Jacksonで使える注釈(アノテーション)や、Javaでのプロパティ(getter/setter)を活用すれば、もっとすごいことが簡単にできます。

こういうことがやりたいなというようなことへは、Jacksonでは大抵やり方がありますので、困ったときはドキュメントやインターネットの情報をチェックしてみましょう。

私たちは、全てのエンジニアに市場価値を高め自身の望む理想のキャリアを歩んでいただきたいと考えています。もし、今あなたが転職を検討しているのであればこちらの記事をご一読ください。理想のキャリアを実現するためのヒントが見つかるはずです。

『技術力』と『人間力』を高め市場価値の高いエンジニアを目指しませんか?

私たちは「技術力」だけでなく「人間力」の向上をもって遙かに高い水準の成果を出し、関わる全ての人々に感動を与え続ける集団でありたいと考えています。

高い水準で仕事を進めていただくためにも、弊社では次のような環境を用意しています。

  • 定年までIT業界で働くためのスキル(技術力、人間力)が身につく支援
  • 「給与が上がらない」を解消する6ヶ月に1度の明確な人事評価制度
  • 平均残業時間17時間!毎週の稼動確認を徹底しているから実現できる働きやすい環境

現在、株式会社ボールドでは「キャリア採用」のエントリーを受付中です。

まずは以下のボタンより弊社の紹介をご覧いただき、あなたの望むキャリアビジョンをエントリーフォームより詳しくお聞かせください。

コメント

公式アカウントLINE限定!ボールドの内定確率が分かる無料診断実施中
公式アカウントLINE限定!
ボールドの内定確率が分かる無料診断実施中