
JavaのJSONとは?データ構造を見やすく表現するデータ形式「JSON」を解説
プログラミングをしていると“JSON”という言葉をよく見かけませんか?
「JSONって一体何? そもそもどう読むの? じぇーえすおーえぬ?」という方もいらっしゃるでしょう。実は私も、結構最近までそんな人でした。うわー、恥ずかしい…。
JSON(ジェイソン、JavaScript Object Notation)とは、HTMLやXML、CSVのようなデータ形式の一つです。
プログラムでJSONを使えると、とても色々なことができるようになり、世界が大きく広がります。なぜかというと、例えばTwitterやFacebook、GoogleなどのWEBサービスとはJSONでやりとりするからです。
つまり、JSONが分かれば、世の中にあるWEBサービスの色々な機能を自分で使えるようになるのです!!そんな自分を想像してみると、とてもワクワクしませんか? イケてるし、格好いいなぁと思いませんか?
この記事では、JSONの簡単な説明と、JavaからJSONを使うにはどうすればいいのかを、JSONの初心者向けにお伝えします!!
※この記事のサンプルは、Java 10の環境で動作確認しています。
目次
1.JSONとはどんなものだろう
1-1.JSONはデータ構造を見やすく表現できるデータ形式
JSON(ジェイソン、JavaScript Object Notation)とは、データ形式の一つです。JSONは「構造」を持ったデータを、見やすい形で表現するのが得意です。TwitterやFacebook、Googleなどのインターネット上の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)
では、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 (https://github.com/FasterXML/jackson)
- Gson (https://github.com/google/gson)
- JSON in Java (http://stleary.github.io/JSON-java/)
- JSON-P (JSON Processing、JSR 353の実装、https://javaee.github.io/jsonp/)
以下、この記事ではJacksonを使ったJavaプログラムの例をお伝えします。
Jacksonは広く使われているライブラリで、使い方・活用方法などの情報もインターネットで豊富に入手できます。
バージョンアップもずっと続いていますので、これからもどんどん使いやすくなることが期待できますよ。
ちなみに、AndroidのプログラムではGsonが広く使われていますし、JSON in Javaもとても良く使われています。ですので、いくつかのライブラリの使い方を知っておくのもいいでしょう。
3.Jacksonの使い方の基本
JacksonでJSONを読み書きするには、大きく分けると以下の二つの方法があります。
- JSONのデータ構造と同じクラスを作り、JSONと紐付けて読み書きする
- JsonNode/ObjectNodeを使う方法:JSONのデータ構造を扱えるクラスで読み書きする
直感的にプログラミングできるのは1.です。基本的にはこちらをお勧めします。でも、2.のやり方も知っていると便利でしょう。複雑な構造を持つJSONだと、対応するクラスを作ることそのものが大変な場合もあるからです。
この章では、Jacksonを使うためのプロジェクトのセットアップと、これら二つの方法でのプログラミングの仕方を、簡単にご紹介します。
3-1.Jacksonを使えるようにしよう!
JacksonはJavaの標準APIには含まれていませんので、あなたのプログラムから使うには少しセットアップが必要となります。
セットアップには、MavenやGradleなどのプロジェクト管理ツールを使う方法と、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.jar、jackson-databind-2.x.x.jar、jackson-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を含めなければなりません。具体的には、以下のように設定しましょう。皆さんの環境に合わせて、読み替えいただく必要がある箇所があるかもしれませんね。
3-2.JSONとクラスを紐付けて使う場合
3-2-1.JSONをJavaのインスタンスに変換する
Jacksonを使うときは、ObjectMapper.readValueを使うと、直感的にJSONをJavaクラスのインスタンスにできます。
まず、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が用意しているクラスのJsonNodeやObjectNodeを使っても、JSONをJavaから利用できます。
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をベースに、一部だけ値を変更したり、プロパティを追加できたりすれば、楽が出来ますよね。
その場合は、JsonNodeをObjectNodeに変換してしまいましょう。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ページ
- https://github.com/FasterXML/jackson
- [英語]Jacksonの情報が盛りだくさんです!!
公式ドキュメント
- https://github.com/FasterXML/jackson-docs
- [英語]チュートリアルやJacksonクラスの使い方などの詳細情報
公式Javadoc
- https://github.com/FasterXML/jackson-docs/wiki/Finding-Javadoc
- [英語]JavaではJavadocは基本中の基本!! Jacksonで困ったら、まずはJavadocを確認しましょう。
- http://fasterxml.github.io/jackson-core/javadoc/2.9/
- http://fasterxml.github.io/jackson-databind/javadoc/2.9/
- http://fasterxml.github.io/jackson-annotations/javadoc/2.9/
Mavenリポジトリ
- https://mvnrepository.com/artifact/com.fasterxml.jackson.core
- Maven以外にも、Gradle/SBT/Ivy/Grape/Leiningen/Builder用の定義もあります。
- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations
jarの直接ダウンロード元
- http://repo1.maven.org/maven2/com/fasterxml/jackson/core/
- Jacksonのjarは、過去バージョンも含めてMavenリポジトリからダウンロードできます。
- http://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-core/
- http://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-databind/
- http://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-annotations/
Stack OverflowのJacksonに関するQ&A
- https://stackoverflow.com/questions/tagged/java+jackson
- [英語]英語版Stack Overflowでjavaとjacksonのタグが付いているQ&A
- https://ja.stackoverflow.com/questions/tagged/java+jackson
- [日本語]日本語版Stack Overflowでjavaとjacksonのタグが付いているQ&A
5.まとめ
この記事では、JSONとはどんなものか、JSONをJavaから扱うためのライブラリにはどんなものがあるか、そのライブラリの一つJacksonの使い方について基本をお伝えしました。
JSONとは、データ構造とプロパティの値を、人間にとって見やすく記述できるデータ形式です。
JacksonのObjectMapperを使えば、JSONとJavaのクラスを紐付けて、直感的にJSONの読み書きができます。Javaのクラスを紐付けない場合は、JsonNodeやObjectNodeを使えばJSONを読み書きできます。この二つのやり方は、プログラムでの用途に応じて使い分けましょう。
なお、今回お伝えしたのはJacksonが本来持つ実力の、ほんの一部です。Jacksonで使える注釈(アノテーション)や、Javaでのプロパティ(getter/setter)を活用すれば、もっとすごいことが簡単にできます。
こういうことがやりたいな…というようなことへは、Jacksonでは大抵やり方がありますので、困ったときはドキュメントやインターネットの情報をチェックしてみましょう。
コメント