だましだまし

そういう生き方 メモ用として使っていく

jsonicのlistだけを持つクラスを使いたくない場合

jsonicの話。
まず下記みたいなjsonが欲しいっていうとき

{"data":[{"id":"001","name":"bean001"},{"id":"002","name":"bean002"}]}

この場合まずbeanクラスを用意する
TestJSONBean.java

public class TestJSONBean {
	public String id;
	public String name;
}

で、ここまでは良いとして、このあとによく下記のようなクラスをサンプルとかで見かける。
TestJSONData.java

import java.util.List;

public class TestJSONData {
	public List<TestJSONBean> data;
}

これにプラスでメンバにIDとかある奴もあったりしてそれなら分かるんだけど、少なくともこのクラスはあんまり作りたくないなと思う。
なんかこのクラスの存在自体が美しくないっていうか、なので回避策ないかなーって思ったら割りとあっさり出来た。
まずこの上記のクラスを素直に使った場合のencode・decode。

@Test
public void jsonic001() {
	TestJSONData jsonData = new TestJSONData();
	List<TestJSONBean> list = new ArrayList<>();
	TestJSONBean bean001 = new TestJSONBean();
	bean001.id = "001";
	bean001.name = "bean001";
	TestJSONBean bean002 = new TestJSONBean();
	bean002.id = "002";
	bean002.name = "bean002";
	list.add(bean001);
	list.add(bean002);
	jsonData.data = list;
	String jsonString = JSON.encode(jsonData);
	System.out.println("encode→" + jsonString);
	jsonData = JSON.decode(jsonString, TestJSONData.class);
	jsonString = JSON.encode(jsonData);
	System.out.println("decode→encode→" + jsonString);
}

「え? なにそのテストコード見づらい……」っていう苦情には答えられない。
で、これの結果が下記。

encode→{"data":[{"id":"001","name":"bean001"},{"id":"002","name":"bean002"}]}
decode→encode→{"data":[{"id":"001","name":"bean001"},{"id":"002","name":"bean002"}]}

当然期待通りの動作をする。
で、回避策としてMapにしてみようとしたコードが次の通り。

@Test
public void jsonic002() {
	List<TestJSONBean> list = new ArrayList<>();
	TestJSONBean bean001 = new TestJSONBean();
	bean001.id = "001";
	bean001.name = "bean001";
	TestJSONBean bean002 = new TestJSONBean();
	bean002.id = "002";
	bean002.name = "bean002";
	list.add(bean001);
	list.add(bean002);
	Map<String, List<TestJSONBean>> map = new HashMap<>();
	map.put("data", list);
	String jsonString = JSON.encode(map);
	System.out.println("encode→" + jsonString);
	map = JSON.decode(jsonString);
	jsonString = JSON.encode(map);
	System.out.println("decode→encode→" + jsonString);
	System.out.println("map.get(\"data\"):" + map.get("data").toString());
}

結果

encode→{"data":[{"id":"001","name":"bean001"},{"id":"002","name":"bean002"}]}
decode→encode→{"data":[{"id":"001","name":"bean001"},{"id":"002","name":"bean002"}]}
map.get("data"):[{id=001, name=bean001}, {id=002, name=bean002}]

期待通りの動作になった。
どうしてもTestJSONData.javaみたいなクラスを作りたくないっていう人はこれでやるのもいいかも。
「いや、そもそもjsonic遅いから使ってねーよ」っていう人はなぜここまでこの記事読んだのかを聞きたい。
jacksonの方が遥かに速いのは間違いないけども。