こんにちは!フリーランスの長野です。
JavaでJSONデータって使っていますか?JSONデータを使うことで、データベースをテキスト形式で簡単にかつ軽量に扱うことができるので便利です。
JSONデータは元々JavaScriptで扱うデータ形式ですが、Javaでも扱うことができます。この記事では、JSONデータの扱い方について
- JSONとは
- JacksonでJSONデータを扱う方法
- JSON In JavaでJSONデータを扱う方法
といった基本的な内容から標準APIでJSONデータを扱う方法など応用的な内容についても解説していきます。今回はJSONデータの扱い方について、使い方をわかりやすく解説します!
なお、Javaの記事については、こちらにまとめています。
JSONとは
JSONとは、JavaScript Object Notationの略称でJavaScriptにおけるオブジェクトの表記法をベースとした軽量なデータ記述言語のことです。
JavaScriptにおけるオブジェクトの表記法ですが、JavaScript以外の言語でも使うことができます。もちろんJavaでも扱うことができます。どのようなものか、以下の例で確認しましょう。
{“name”: “Taro Tanaka”, “age”: 30}
連想配列のように{“キー”: “値”}の形式になっています。キーと値をセットで扱うので、軽量なデータベースとして使用することができます。連想配列を扱うクラスとして、JavaにはHashMapクラスがあります。
ですので、JSONデータはHashMapクラスのオブジェクトに変換して扱われることも多いです。また、配列のように[値1, 値2, ・・・]の形式も扱うこともできます。
JavaでJSONデータを扱うには、標準APIで扱う方法もありますが、JacksonやJSON In Javaのようにライブラリを使って扱う方法もあります。それぞれの方法について、詳しく解説していきます!
JacksonでJSONデータを扱う方法
標準APIを使う場合は後ほど解説しますが、少々処理が面倒になります。ライブラリを使うと処理の記述が簡単になります。そこでまずはライブラリJacksonを使う方法をご紹介します。
Jacksonを使うと、クラスオブジェクトとJSONデータとを変換する場合に便利です。
ライブラリの準備
3つのライブラリが必要になります。
リンク先のサイトが開いたら、Versionをクリックして選択してください。最新のVersionを選ぶとよいでしょう。
“bundle”ボタンを押すとjarファイルのダウンロードが開始されます。
jarファイルがダウンロードできたら、クラスパスを通すことで使えるようになります。クラスパスを通す方法は、Eclipseという開発環境を使用すると簡単にできますので、その方法をご紹介します。
Eclipseのプロジェクト名を右クリックして、「ビルド・パス」→「外部アーカイブの追加」を選択することでjarファイルを登録し、クラスパスを追加することができます。他のjarファイルも同じように登録します。
これでライブラリが使えるようになりました。なお、開発環境Eclipseの使い方については、こちらで詳しく解説していますので、ぜひ参考にしてください。
クラスオブジェクトへdecode(変換)
JacksonではクラスオブジェクトとJSONデータとを変換するのに便利なクラス、メソッドがそろっています。JSONデータをクラスオブジェクトに変換する方法についてみていきましょう。クラスオブジェクトに変換するには、まずObjectMapperクラスを使ってインスタンスを生成します。
生成したオブジェクトからreadValueメソッドを呼び出して使用することで、クラスオブジェクトを生成することができます。サンプルコードで確認しましょう。
import java.io.IOException; import com.fasterxml.jackson.databind.ObjectMapper; class Info { public String name; public int age; } public class Main { public static void main(String[] args) { String script = "{ "name":"Taro Tanaka", "age":30}"; ObjectMapper mapper = new ObjectMapper(); try { Info info = mapper.readValue(script, Info.class); System.out.println(info.name + ", " + info.age); } catch (IOException e) { e.printStackTrace(); } } }
実行結果:
Taro Tanaka, 30
このサンプルコードでは、ObjectMapperクラスのreadValueメソッドを使ってクラスオブジェクトinfoを生成し、そのメンバの値を出力表示しています。
ObjectMapperクラスを使うには、com.fasterxml.jackson.databind.ObjectMapperクラスをインポートする必要があります。
また、エラー処理を記述する必要があり、たくさんの例外クラスで処理する必要があるため、java.io.IOExceptionクラスでまとめて例外処理をしています。
JSONデータへencode
JSONデータに変換する場合にも、まずObjectMapperクラスを使ってインスタンスを生成します。生成したオブジェクトからwriteValueAsStringメソッドを呼び出して使用することで、JSONデータを生成することができます。
サンプルコードで確認しましょう。
import java.io.IOException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; class Info { public String name; public int age; } public class Main { public static void main(String[] args) { Info info = new Info(); info.name = "Taro Tanaka"; info.age = 30; ObjectMapper mapper = new ObjectMapper(); mapper.enable(SerializationFeature.INDENT_OUTPUT); try { String script = mapper.writeValueAsString(info); System.out.println(script); } catch (IOException e) { e.printStackTrace(); } } }
実行結果:
{ "name" : "Taro Tanaka", "age" : 30 }
このサンプルコードでは、ObjectMapperクラスのwriteValueAsStringメソッドを使ってJSONデータscriptを生成し、出力表示しています。
なお、ObjectMapperクラスのenableメソッドを使って、引数にSerializationFeature.INDENT_OUTPUTを指定することで、JSONデータの表示形式を整えることができます。これをシリアライズと呼びます。
逆に、クラスオブジェクトの形式に整えることをデシリアライズと言います。
JSONテキストの読み込み
これまでは比較的簡単なJSONデータを扱う方法について解説してきました。実際のデータは要素数も多く、連想配列や配列が入り混じっていて、複雑な構造をしていることが多いです。そんなJSONデータを扱う方法について解説します。
JSONデータのサンプルとして、以下のサイトで記載されているデータを使用します。
http://www.oracle.com/technetwork/jp/articles/java/ja-topics/json-1973242-ja.html
sample.json:
{ "firstName":"John", "lastName":"Smith", "age":25, "address":{ "streetAddress":"21 2nd Street", "city":"New York", "state":"NY", "postalCode":10021 }, "phoneNumbers":[ { "type":"home", "number":"212 555-1234212 555-1234" }, { "type":"fax", "number":"646 555-4567646 555-4567" } ] }
連想配列の値の中に連想配列が入れ子になったり、連想配列の値の中に配列を指定し、さらに配列の要素が連想配列といったように複雑な構成になっています。
このJSONファイルを読み込んで要素を取得する方法について確認しましょう。ObjectMapperクラスのreadTreeメソッドを使ってJSONファイルを読み込み、JsonNodeオブジェクトに格納します。JsonNodeオブジェクトからgetメソッドを呼び出し、要素を取得します。
import java.io.File; import java.io.IOException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; public class Main { public static void main(String[] args) { ObjectMapper mapper = new ObjectMapper(); try { JsonNode node = mapper.readTree(new File("sample.json")); int age = node.get("age").asInt(); System.out.println(age); String city = node.get("address").get("city").asText(); System.out.println(city); String number = node.get("phoneNumbers").get(0).get("number").asText(); System.out.println(number); } catch (IOException e) { e.printStackTrace(); } } }
実行結果:
25 New York 212 555-1234212 555-1234
このサンプルコードでは、ObjectMapperクラスのreadTreeメソッドを使ってJSONファイルsample.jsonを読み込み、JsonNodeオブジェクトnodeに格納しています。
JsonNodeオブジェクトnodeからgetメソッドを呼び出し、要素を取得しています。getメソッドの引数には連想配列のキーの値を指定し、連想配列の値を取得しています。
配列の要素の値を取得するには、配列のインデックス番号を指定しています。ご紹介したObjectMapperクラスやJsonNodeクラスのメソッドの詳しい内容について、こちらのサイトを参考にしてみてください。
ObjectMapper:
https://fasterxml.github.io/jackson-databind/javadoc/2.8/com/fasterxml/jackson/databind/ObjectMapper.html
JSON In JavaでJSONデータを扱う方法
ライブラリJSON In JavaでもJSONデータを簡単に扱うことができます。JSON In Javaを使うと、Map型やList型のオブジェクトとJSONデータとを変換する場合に便利です。
ライブラリの準備
ライブラリはこちらから入手できます。
https://mvnrepository.com/artifact/org.json/json
Versionを選択して、”bundle”ボタンを押すとjarファイルのダウンロードが開始されます。ダウンロードできたら、ファイルを先ほどと同じようにEclipseの”ビルド・パス”でクラスパスを追加して、参照ライブラリに登録します。
JSONObjectクラスを使ったJSONデータの作り方について解説します。
基本的な使い方
JSONObjectクラスを使うには、org.json.JSONObjectをインポートする必要があります。JSONObjectクラスのインスタンスを生成し、生成したオブジェクトからputメソッドを使って仮想配列の要素を追加していきます。サンプルコードで確認しましょう。
import org.json.JSONObject; public class Main { public static void main(String[] args) { JSONObject obj = new JSONObject(); obj.put("name", "Taro Tanaka"); obj.put("age", 30); System.out.println(obj); } }
実行結果:
{"name":"Taro Tanaka","age":30}
配列へdecode(変換)
JSONArrayクラスを使うと、配列形式とJSONデータとを相互変換することができます。JSONArrayクラスを使うには、org.json.JSONArrayをインポートする必要があります。
JSONArrayクラスのインスタンスを生成するときに、コンストラクタの引数にJSONデータ形式のテキストを指定するだけで、JSONデータに変換できます。サンプルコードで確認しましょう。
import java.util.ArrayList; import java.util.List; import org.json.JSONArray; public class Main { public static void main(String[] args) { String script = "[ "Taro", "Tanaka"]"; JSONArray arr = new JSONArray(script); List<String> list = new ArrayList<>(); for(Object str : arr) { list.add((String) str); } System.out.println(list); } }
実行結果:
["Taro","Tanaka"]
JSONArrayクラスのコンストラクタやメソッドなどの詳細については、こちらのサイトを参照してみてください。
https://stleary.github.io/JSON-java/org/json/JSONArray.html
Mapオブジェクトへdecode
JSONObjectクラスを使うと、Map型のオブジェクトとJSONデータとを相互変換することができます。JSONObjectクラスを使うには、org.json.JSONObjectをインポートする必要があります。
JSONObjectクラスのインスタンスを生成するときに、コンストラクタの引数にJSONデータ形式のテキストを指定するだけで、JSONデータに変換できます。サンプルコードで確認しましょう。
import java.util.HashMap; import java.util.Map; import org.json.JSONObject; public class Main { public static void main(String[] args) { String script = "{ "name":"Taro Tanaka", "age":30}"; JSONObject obj = new JSONObject(script); Map<String, Object> map = new HashMap<>(); for(Object key : obj.keySet()) { map.put((String) key, obj.get((String) key)); } System.out.println(map); } }
実行結果:
{name=Taro Tanaka, age=30}
このサンプルコードでは、JSONデータからJSONObjectクラスを使ってJSONObjectオブジェクトobjを生成しています。JSONObjectオブジェクトobjを使って、Map型のオブジェクトmapに要素を格納しています。
なお、JSONObjectクラスではMap型のオブジェクトのようにentrySetメソッドが使えません。ですが、keySetメソッドは使えますので、それを使って拡張for文でMap型のオブジェクトmapに要素を格納しています。
JSONObjectクラスのコンストラクタやメソッドなどの詳細については、こちらのサイトを参照してみてください。
https://stleary.github.io/JSON-java/org/json/JSONObject.html
また、Map型のオブジェクトでキーと値を取得する方法については、こちらで詳しく解説しています。ぜひ参考にしてください。
JSONObjectへencode
JSONObjectクラスのインスタンスを生成するときに、コンストラクタの引数にMap型のオブジェクトを指定するだけで、JSONデータに変換できます。サンプルコードで確認しましょう。
import java.util.HashMap; import java.util.Map; import org.json.JSONObject; public class Main { public static void main(String[] args) { Map<String, Object> map = new HashMap<>(); map.put("name", "Taro Tanaka"); map.put("age", 30); JSONObject obj = new JSONObject(map); System.out.println(obj); } }
実行結果:
{"name":"Taro Tanaka","age":30}
JSONArrayへencode
JSONArrayクラスのインスタンスを生成するときに、コンストラクタの引数にList型のオブジェクトを指定するだけで、JSONデータに変換できます。サンプルコードで確認しましょう。
import java.util.ArrayList; import java.util.List; import org.json.JSONArray; public class Main { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("Taro"); list.add("Tanaka"); JSONArray arr = new JSONArray(list); System.out.println(arr); } }
実行結果:
["Taro","Tanaka"]
標準APIでJSONデータを扱う方法
これまでは、ライブラリを使ってJSONデータを扱う方法についてお伝えしてきました。Javaではライブラリを使わずに標準APIを使うことでJSONファイルを扱うこともできます。JavaにはJavaScriptエンジンが用意されているので、JavaでもJavaScriptを扱うことができます。
Java6からJavaScriptを扱うことができるようになり、RhinoというJavaScriptエンジンを使用していました。Java8からは新たにNashornというJavaScriptエンジンが追加され、Rhinoから置き換えることができます。今回はNashornを使ってJSONデータを扱う方法についてご紹介します。
Mapオブジェクトへdecode(変換)
JavaでJavaScriptを扱うためには、まずScriptEngineManagerクラスを使ってインスタンスを生成します。そのオブジェクトからgetEngineByNameメソッドを呼び出し、引数にエンジンnashornを指定します。そして、evalメソッドを使って、JavaScriptを実行します。
サンプルコードで確認しましょう。
import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; public class Main { public static void main(String[] args) { String script = "{ "name":"Taro Tanaka", "age":30}"; ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine engine = manager.getEngineByName("nashorn"); try { // JavaScriptの実行 Object obj = engine.eval(String.format("(%s)", script)); // リフレクションでScriptObjectMirrorクラスの取得 Class scriptClass = Class.forName("jdk.nashorn.api.scripting.ScriptObjectMirror"); // リフレクションでキーセットを取得 Object[] keys = ((java.util.Set)obj.getClass().getMethod("keySet").invoke(obj)).toArray(); // リフレクションでgetメソッドを取得 Method method_get = obj.getClass().getMethod("get", Class.forName("java.lang.Object")); Map<String, String> map = new HashMap<>(); for(Object key : keys) { Object val = method_get.invoke(obj, key); map.put(key.toString(), val.toString()); } System.out.println(map); } catch(Exception e) { e.printStackTrace(); } } }
実行結果:
{name=Taro Tanaka, age=30}
このサンプルコードではリフレクションを使って、JavaScriptでJSONデータを扱うScriptObjectMirrorクラスを使用しています。そしてScriptObjectMirrorクラスのkeySetメソッドを使って、リフレクションでキーセットを取得しています。
また値を取得するために、getメソッドをリフレクションで取得して使っています。なお、ScriptObjectMirrorクラスのメソッドの詳しい内容については、こちらを参考にしてみてください。
リフレクションについては、こちらで詳しく解説していますので、ぜひ参考にしてください。
まとめ
ここでは、JSONデータの扱い方について説明しました。JSONデータを使うことで、データベースをテキスト形式で簡単にかつ軽量に扱うことができるので便利です。
使いこなすことができるように、この記事を何度も参考にして下さいね!