Jacksonを使ってみた

やりたいこと

- JavaのオブジェクトをJSON文字列に簡単に変換したい
- JSON文字列をJavaのオブジェクトに簡単に変換したい
- JSONの要素名を小文字アンダーバー区切り(snake_case)にしたい
- オブジェクトのメンバーにenumがある場合はenum列挙子固有の任意の整数値をvalueにしたい
 - 何種類もenumがあっても最小限のコード追加で同様のことができるようにしたい
- 日付のフォーマットをISO8601にしたい
- 改行・インデントがある形式のJSON文字列を作りたい
- 単体オブジェクトとListオブジェクトに対応

```java:JacksonTest.java
package sandbox;

import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonValue;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;

public class JacksonTest {
	long id;
	String name;
	Type type;
	Date createdAt;
	@JsonIgnore boolean fooFlag;

	public JacksonTest() {
	}

	public JacksonTest(long id, String name, Type type, Date createdAt, boolean fooFlag) {
		this.id = id;
		this.name = name;
		this.type = type;
		this.createdAt = createdAt;
		this.fooFlag =fooFlag;
	}

	public long getId() {
		return id;
	}


	public void setId(long id) {
		this.id = id;
	}


	public String getName() {
		return name;
	}


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


	public Type getType() {
		return type;
	}


	public void setType(Type type) {
		this.type = type;
	}


	public Date getCreatedAt() {
		return createdAt;
	}


	public void setCreatedAt(Date createdAt) {
		this.createdAt = createdAt;
	}

	public boolean isFooFlag() {
		return fooFlag;
	}

	public void setFooFlag(boolean fooFlag) {
		this.fooFlag = fooFlag;
	}

	public static void main(String[] args) throws Exception {
		// 単体
		JacksonTest obj = new JacksonTest(1234L, "ガンダム", Type.ROBOT, new Date(), true);
		ObjectMapper mapper = new ObjectMapper();
		mapper.setPropertyNamingStrategy(PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES);
		mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX"));// ISO8601

		String jsonStr = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
		System.out.println(jsonStr);

		JacksonTest dest = mapper.readValue(jsonStr, JacksonTest.class);
		System.out.println(dest.id + ", " + dest.name + ", " + dest.type + ", " + dest.createdAt + ", " + dest.fooFlag);

		// List
		List<JacksonTest> list = new ArrayList<JacksonTest>() {{
			add(new JacksonTest(1234L, "ガンダム", Type.ROBOT, new Date(), true));
			add(new JacksonTest(1235L, "アベ総理", Type.HUMAN, new Date(), true));
			add(new JacksonTest(1236L, "猫ひろし", Type.ANIMAL, new Date(), true));
		}};

		jsonStr = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(list);
		System.out.println(jsonStr);

		List<JacksonTest> destList = mapper.readValue(jsonStr, new TypeReference<List<JacksonTest>>(){});
		System.out.println("size = " + destList.size());
		System.out.println(destList.get(1).getName());

	}
}

enum Type implements JsonEnumInt {
	HUMAN(1),
	ANIMAL(2),
	ROBOT(100);
	private int value;
	private Type(int value) {
		this.value = value;
	}

	@JsonValue
	@Override
	public int getValue() {
		return value;
	}

	@JsonCreator
	public static Type fromValue(int value) {
		return Util.getEnumFromValue(value, Type.class);
	}
}

interface JsonEnumInt {
	public int getValue();
}

class Util {
	public static <E extends JsonEnumInt> E getEnumFromValue(int value, Class<E> clazz) {
		try {
			Method method = clazz.getMethod("values");
			@SuppressWarnings("unchecked")
			E[] array = (E[]) method.invoke(null);
			for (E e : array) {
				if (e.getValue() == value) {
					return e;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
}
```

結果

>{
>&nbsp;&nbsp;"id" : 1234,
>&nbsp;&nbsp;"name" : "ガンダム",
>&nbsp;&nbsp;"type" : 100,
>&nbsp;&nbsp;"created_at" : "2013-06-03T14:42:55+09:00"
>}
>1234, ガンダム, ROBOT, Mon Jun 03 14:42:55 JST 2013, false
>[ {
>&nbsp;&nbsp;"id" : 1234,
>&nbsp;&nbsp;"name" : "ガンダム",
>&nbsp;&nbsp;"type" : 100,
>&nbsp;&nbsp;"created_at" : "2013-06-03T14:42:55+09:00"
>}, {
>&nbsp;&nbsp;"id" : 1235,
>&nbsp;&nbsp;"name" : "アベ総理",
>&nbsp;&nbsp;"type" : 1,
>&nbsp;&nbsp;"created_at" : "2013-06-03T14:42:55+09:00"
>}, {
>&nbsp;&nbsp;"id" : 1236,
>&nbsp;&nbsp;"name" : "猫ひろし",
>&nbsp;&nbsp;"type" : 2,
>&nbsp;&nbsp;"created_at" : "2013-06-03T14:42:55+09:00"
>} ]
>size = 3
>アベ総理