jsonicを使ってみる
ちょいと事情により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でデコードしたり出来るし、非常に良さそうな感じがする