Java で JSON を扱ってみた。

今回の内容

JSON とは

JSON (JavaScript Object Notation) は、ネットワーク通信などで多く用いられるデータフォーマットです。

[{"name":"太郎","age":30}, {"name":"花子","age":25}]

例えば上記の例は、name: 太郎 age: 30 と name: 花子 age: 25 の2つのオブジェクトが入っている情報になり、JSONは様々な形式のデータをシンプルで比較的小さなサイズで情報を持つことができるのが特徴になります。

JSON は [ ] が配列、{ } が連想配列を意味しており、配列は要素を順番に並べ、連想配列はキーと値の組み合わせを (キー): (値) の形でカンマ区切りで記述していきます。

JSON は JavaScript における配列や連想配列、Python におけるリストと辞書の記述方式と同じであり、それらの言語とは相性が良く変換機能なども最初から用意されているのですが Java は外部ライブラリをインストールし、使用する必要があります。

そこで、今回は、Java で JSON を扱う方法を紹介していきたいと思います。

Java で JSON を扱うための設定

Java で JSON を扱うには Jackson という名前のライブラリを用います。

Jackson は maven プロジェクトであれば、下記の様なコードを pom.xml を dependencies タグの中に追加します。

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>(バージョン番号)</version>
</dependency>

Jackson の最新バージョンは、この記事を書いている令和6年(2024年)2月16日時点では、2.16.1 です。

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

最新バージョンについては Maven のページの Jackson Databind 情報を参考にすると良いでしょう。

https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind

また、英語ではありますが、Jackson の詳細な情報が知りたい場合は GitHub でプロジェクトが動いておりますので、そちらを参考にして頂くと良いと思います。

https://github.com/FasterXML/jackson-databind

Map 情報の入出力

JSON は JavaScript の配列と連想配列の形をしているというお話をしましたが、Java には配列の概念はあるものの、連想配列の概念はありません。

しかし、キーから値を取得するデータとしては Map インタフェースが用意されています。

また、Java の配列は自由にデータの挿入や削除ができない為、配列よりも柔軟性の高い List オブジェクトの方がよく使われます。

そこで、まず List と Map オブジェクトを使った JSON の読み書きの方法をご紹介したいと思います。

入力

Jackson では JSON の読み書きは ObjectMapper を使って行ないます。

ここでは以下の文字列を JSON の文字列の例として使用します。

[{"name":"太郎","age":30}, {"name":"花子","age":25}]

次の例は上記の文字列を Map の List として取得するコードとなります。

String json = "[{\"name\":\"太郎\",\"age\":30}, {\"name\":\"花子\",\"age\":25}]";
System.out.println("json: " + json);

ObjectMapper mapper = new ObjectMapper();
TypeReference<List<Map<String, String>>> typeRef 
    = new TypeReference<List<Map<String, String>>>() {};        
List<Map<String, String>> list 
    = mapper.readValue(json, typeRef);

for(Map<String, String> map : list) {
    System.out.println(
        map.get("name") + "さんは" 
            + map.get("age") + "歳です。"
    );
}

実際に JSON からList, Map に変換している部分は

ObjectMapper mapper = new ObjectMapper();
TypeReference<List<Map<String, String>>> typeRef 
    = new TypeReference<List<Map<String, String>>>() {};        
List<Map<String, String>> list 
    = mapper.readValue(json, typeRef);

で、それより上側は JSON 文字列の準備、下側は結果の確認となります。

上記のコードを実行すると以下の様な出力がされます。

json: [{"name":"太郎","age":30}, {"name":"花子","age":25}]
太郎さんは30歳です。
花子さんは25歳です。

JSON の文字列を Map の List として取得できている事が確認できます。

出力

続いてマップ情報の出力を行なっていきます。

List<Map<String, String>> list
    = new ArrayList<Map<String, String>>();

Map<String, String> taro = new HashMap<String, String>();
taro.put("name", "太郎");
taro.put("age", "30");
list.add(taro);
        
Map<String, String> hanako = new HashMap<String, String>();
hanako.put("name", "花子");
hanako.put("age", "25");  
list.add(hanako);
        
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(list);
        
System.out.println("json: " + json);

これは以下が JSON への変換部分になっており、

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

それより前側は Map と List の準備、後側は JSON の内容の確認になります。

このプログラムを実行すると以下の出力がされ、List と Map がきちんと JSON に変換できている事を確認できます。

json: [{"name":"太郎","age":"30"},{"name":"花子","age":"25"}]

オブジェクト情報の入出力

ここまで、Map と List の情報を JSON で扱う方法をご紹介しましたが、Java では種々の情報を Map で扱うことはそれほど多くはなく、それよりはオブジェクトとしてデータを扱うことの方が圧倒的に多いと思います。

そこで、ここでは Map ではなくオブジェクトを使った JSON の入出力方法についてご紹介したいと思います。

まず、今回の例ではキーとして name (名前) と age (年齢) を扱う Person クラスを定義しておきます。

public static class Person {
    private String name;
    private int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }

    public String toString() {
        return "name: " + name + ", age: " + age;
    }
}

ここで必ず必要となるのが、name と age の ゲッターメソッド(getter) とセッターメソッド (setter)、つまり getName, setName, getAge, setAge になります。

Jackson の ObjectMapper はこれを利用して、JSON の入出力を行ないます。

入力

先ほど作成した Person クラスを使用して、JSON の読込を行ないます。今回も使用する JSON の文字列は以下の例となります。

[{"name":"太郎","age":30}, {"name":"花子","age":25}]
String json = "[{\"name\":\"太郎\",\"age\":30}, {\"name\":\"花子\",\"age\":25}]";
System.out.println("json: " + json);

ObjectMapper mapper = new ObjectMapper();
List<Person> list = mapper.readValue(
    json, new TypeReference<List<Person>>() {}
);

for(Person person : list) {
    System.out.println(person);
}

これは以下の部分が JSON の入力部分になり

ObjectMapper mapper = new ObjectMapper();
List<Person> list = mapper.readValue(
    json, new TypeReference<List<Person>>() {}
);

それより上側が、JSON 文字列の準備、後側が結果の確認になります。

上記のプログラムを実行すると以下の結果が出力され、オブジェクトとして入力できている事が確認できます。

json: [{"name":"太郎","age":30}, {"name":"花子","age":25}]
name: 太郎, age: 30
name: 花子, age: 25

尚「name: 太郎, age: 30」は Person クラスで toString メソッドを実装することで、この様な文字列になるように設定してあります。

出力

続いてオブジェクト情報を JSON として出力していきます。

List<Person> list = new ArrayList<Person>();
list.add(new Person("太郎", 30));
list.add(new Person("花子", 25));

ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(list);
        
System.out.println("json: " + json);

これは以下の部分が出力の部分になり

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

それより前側がオブジェクトの準備、後側が JSON 文字列の確認になります。

結果、以下の様な出力になり、オブジェクトから JSON 文字列を生成できている事が確認できます。

json: [{"name":"太郎","age":30},{"name":"花子","age":25}]

まとめ

Java で JSON を扱うには Jackson の ObjectMapper で入出力ができる事が確認できました。

ネットワークで公開されている様々なシステムが JSON で情報取得をできる様になっているので、覚えておくと役に立つ場面も色々と出てきますし、今後その様な例をこのブログでも扱っていきたいと思います。