jsonicを使ってみる

2012-12-23T00:00:00+00:00 Java

ちょいと事情によりorg.jsonじゃなくてjsonicを使う事案が出てきて勉強している。まだまだ勉強途中だけどとりあえずまとめてみた。

まずObjectからJSONに変換するベースとなるクラスを作る

import net.arnx.jsonic.JSONHint;

public class Sample {

    @JSONHint(name="sample_name")
    public String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

JSONHintアノテーションを使う事でJSONにエンコード・デコードする際に対応するキー名をマッピング出来る模様。例えば適当に値ぶち込んでエンコードした場合

{"name":"hoge","sample_name":"hoge"}

というようなJSONが出力される。ただ元プロパティ名とJSONHintで指定した名前両方出るんだけど、JSONHintだけのを出すように抑制する方法が今の所まだ判明してない...

でどんな型がどういう形式でエンコードされるのかについては公式ドキュメントに書いてあるので省略。という事でざっくりと使ってみる

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.HashMap;

import org.junit.Test;

import net.arnx.jsonic.JSON;
import net.arnx.jsonic.JSONEventType;
import net.arnx.jsonic.JSONException;
import net.arnx.jsonic.JSONReader;

import static org.junit.Assert.*;
import static org.hamcrest.Matchers.*;

public class SampleTestCase {

    @Test
    public void test1() {
        Map<String, Object> data = new HashMap<String, Object>();
        data.put("name", "hoge");

        JSON json = new JSON(JSON.Mode.STRICT);
        assertThat(json.getMode(), is(JSON.Mode.STRICT));

        String dataJsonOutput = json.format(data);
        assertThat(dataJsonOutput, is("{"name":"hoge"}"));
    }

    @Test
    public void test2() {
        // JSONを上記のSampleクラスの配列としてデコードして取得する
        Sample[] samples1 = JSON.decode("[{"name": "hoge"}]", Sample[].class);
        assertThat(samples1.length, is(1));

        Sample sample1 = samples1[0];
        assertThat(sample1, is(notNullValue()));
        assertThat(sample1.getName(), is("hoge"));

        // もしList型で利用したい場合はこんな感じで使う
        @SuppressWarnings("serial")
        Type sampleListGenericType = (
            new ArrayList<Sample>() {}
        ).getClass().getGenericSuperclass();

        // JSONHintな方式でデコード出来るかテスト
        List<Sample> samples2 = JSON.decode("[{"sample_name": "fuga"}]", sampleListGenericType);

        /* 以下な感じでも良い模様
        List<Sample> samples2 = JSON.decode("[{"sample_name": "fuga"}]", new TypeReference<List<Sample>>() {});
        */

        assertThat(samples2, is(hasSize(1)));

        Sample sample2 = samples2.get(0);
        assertThat(sample2, is(notNullValue()));
        assertThat(sample2.getName(), is("fuga"));
    }

    @Test
    public void test3() {
        Sample s1 = new Sample();
        s1.setName("hoge");

        String json1 = JSON.encode(s1);

        JSON.validate(json1);

        Sample s2 = JSON.decode(json1, Sample.class);
        assertThat(s2, is(notNullValue()));
        assertThat(s2.getName(), is("hoge"));
    }

    @Test(expected=JSONException.class)
    public void test4() {
        JSON.encode(null);
    }

    @Test(expected=JSONException.class)
    public void test5() {
        // 検証に失敗したらJSONExceptionがスローされる
        JSON.validate("");
    }

    @Test
    public void test6() {
        // JSON構文解析を利用する事も出来る
        JSONReader r = new JSON().getReader("[{"name": "hoge"}]");

        JSONEventType event;

        Map<String, Object> jsonStruct = new HashMap<String, Object>();

        try {
            while ((event = r.next()) != null) {
                jsonStruct.put(event.name(), r.getString());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        assertThat(
            jsonStruct.keySet(),
            is(
                containsInAnyOrder(
                    "START_ARRAY",
                    "START_OBJECT",
                    "NAME",
                    "STRING",
                    "END_OBJECT",
                    "END_ARRAY"
                )
            )
        );
    }
}

staticメソッド使うかインスタンスメソッド使うかでメソッド名が違う。エンコードの場合前者(staticメソッド)はencode、後者(インスタンスメソッド)がformatになる。デコードの場合は前者がdecodeで、後者がparseになる模様

で良くあるパターンとしてList<Sample>っていう形式で出力したい場合にTypeReference使う方が良いとは思うけど、毎回newしたりするのもどうかと思うんでstaticクラスとか書いとけばええんでねーかなと

public static class SampleListTypeRefernece extends TypeReference<List<Sample>> {
}

なだけ書いとくとか

まぁそんな感じでJavaでオブジェクトをJSONでデコードしたり出来るし、非常に良さそうな感じがする

EclipseでGradle PHPUnitを使ってprivateメソッドをテストする