読者です 読者をやめる 読者になる 読者になる

「Java」JSON ライブラリ ( Jackson ) を使ってみた

JavaJSON 形式のデータを触ってみたので、その時のメモ。
ライブラリとしては、以下のようにいろいろあるみたいですが、今回は Jackson を使ってみることに。

・Jackson JSON Processor - Home
http://jackson.codehaus.org/
google-gson - A Java library to convert JSON to Java objects and vice-versa - Google Project Hosting
https://code.google.com/p/google-gson/
JSON Processing
https://jsonp.java.net/

Jackson では JSON 形式のデータを扱うために、3 つの方法を用意してるみたいです。
---------------
1. Streaming API
2. Tree Model
3. Data Binding
---------------

とりあえず、チュートリアルを参考にひと通り使ってみます。

・JacksonInFiveMinutes - FasterXML Wiki
http://wiki.fasterxml.com/JacksonInFiveMinutes
・JacksonStreamingApi - FasterXML Wiki
http://wiki.fasterxml.com/JacksonStreamingApi
・JacksonTreeModel - FasterXML Wiki
http://wiki.fasterxml.com/JacksonTreeModel
・JacksonDataBinding - FasterXML Wiki
http://wiki.fasterxml.com/JacksonDataBinding


入力用の JSON データと POJO は以下の感じで。
■ user.json

{
  "name" : { "first" : "hoge", "last" : "uga" },
  "gender" : "MALE",
  "verified" : false
}

■ User.java

public class User {
	public enum Gender { MALE, FEMALE };

	public static class Name {
		private String _first, _last;

		public String getFirst() {
			return _first;
		}

		public String getLast() {
			return _last;
		}

		public void setFirst(String s) {
			_first = s;
		}

		public void setLast(String s) {
			_last = s;
		}
	}

	private Gender _gender;
	private Name _name;
	private boolean _isVerified;

	public Name getName() {
		return _name;
	}

	public boolean isVerified() {
		return _isVerified;
	}

	public Gender getGender() {
		return _gender;
	}

	public void setName(Name n) {
		_name = n;
	}

	public void setVerified(boolean b) {
		_isVerified = b;
	}

	public void setGender(Gender g) {
		_gender = g;
	}
}


1. Streaming API

■ Parse

private static void StreamingParseTest() {
	try {
		JsonFactory jsonFactory = new JsonFactory();
		// createJsonParser は 2.3.1 では Deprecated みたいです。
		JsonParser jp = jsonFactory.createParser(new File("jackson\\user.json"));

		User user = new User();
		jp.nextToken(); // will return JsonToken.START_OBJECT (verify?)
		while (jp.nextToken() != JsonToken.END_OBJECT) {
			String fieldname = jp.getCurrentName();
			jp.nextToken(); // move to value, or START_OBJECT/START_ARRAY
			if ("name".equals(fieldname)) { // contains an object
				Name name = new Name();
				while (jp.nextToken() != JsonToken.END_OBJECT) {
					String namefield = jp.getCurrentName();
					jp.nextToken(); // move to value
					if ("first".equals(namefield)) {
						name.setFirst(jp.getText());
					} else if ("last".equals(namefield)) {
						name.setLast(jp.getText());
					} else {
						throw new IllegalStateException(
								"Unrecognized field '" + fieldname + "'!");
					}
				}
				user.setName(name);
			} else if ("gender".equals(fieldname)) {
				user.setGender(User.Gender.valueOf(jp.getText()));
			} else if ("verified".equals(fieldname)) {
				user.setVerified(jp.getCurrentToken() == JsonToken.VALUE_TRUE);
			} else {
				throw new IllegalStateException("Unrecognized field '"
						+ fieldname + "'!");
			}
		}
		jp.close();

		System.out.println("name - first : " + user.getName().getFirst());
		System.out.println("name - last : " + user.getName().getLast());
		System.out.println("gender : " + user.getGender());
		System.out.println("verified : " + user.isVerified());
	} catch (JsonParseException e) {
		e.printStackTrace();
	} catch (IOException e) {
		e.printStackTrace();
	}
}


■ Generator

private static void StreamingGeneratorTest() {
	try {
		JsonFactory factory = new JsonFactory();
		// createJsonGenerator は 2.3.1 では Deprecated みたいです。
		JsonGenerator jg = factory.createGenerator(new FileWriter(
				"jackson\\output-streaming.json")); 
				
		jg.writeStartObject();
		jg.writeObjectFieldStart("name");
		jg.writeStringField("first", "Joe");
		jg.writeStringField("last", "Sixpack");
		jg.writeEndObject();
		jg.writeStringField("gender", Gender.MALE.toString());
		jg.writeBooleanField("verified", false);
		jg.writeEndObject();
		jg.close();

	} catch (IOException e) {
		e.printStackTrace();
	}
}


2. Tree Model

■ Parse

private static void TreeModelParseTest() {
	try {
		ObjectMapper m = new ObjectMapper();
		JsonNode rootNode = m.readTree(new File("jackson\\user.json"));

		JsonNode nameNode = rootNode.path("name");
		String firstName = rootNode.path("first").textValue();
		String lastName = nameNode.path("last").textValue();

		JsonNode genderNode = rootNode.path("gender");
		String gender = genderNode.textValue();

		System.out.println(firstName);
		System.out.println(lastName);
		System.out.println(gender);

	} catch (JsonProcessingException e) {
		e.printStackTrace();
	} catch (IOException e) {
		e.printStackTrace();
	}
}


■ Generator

private static void TreeModelGeneratorTest() {
	try {
		ObjectMapper m = new ObjectMapper();
		JsonNode rootNode = m.createObjectNode();
		((ObjectNode) rootNode).put("name", "Tatu");
		m.writeValue(new File("jackson\\output-treemode.json"), rootNode);
	} catch (JsonMappingException e) {
		e.printStackTrace();
	} catch (JsonGenerationException e) {
		e.printStackTrace();
	} catch (IOException e) {
		e.printStackTrace();
	}
}


3. Data Binding

■ Parse

private static void DataBindingParseTest() {
	try {
		ObjectMapper mapper = new ObjectMapper();
		User user = mapper.readValue(new File("jackson\\user.json"),
				User.class);

		System.out.println("name - first : " + user.getName().getFirst());
		System.out.println("name - last : " + user.getName().getLast());
		System.out.println("gender : " + user.getGender());
		System.out.println("verified : " + user.isVerified());
	} catch (JsonMappingException e) {
		e.printStackTrace();
	} catch (JsonParseException e) {
		e.printStackTrace();
	} catch (IOException e) {
		e.printStackTrace();
	}
}


■ Generator

private static void DataBindingGeneratorTest() {
	try {
		User user = new User();
		Name name = new Name();
		name.setFirst("hoge");
		name.setLast("uga");
		user.setName(name);
		user.setGender(Gender.MALE);
		user.setVerified(true);

		ObjectMapper mapper = new ObjectMapper();
		mapper.writeValue(new File("jackson\\output-databinding.json"),
				user);

	} catch (JsonMappingException e) {
		e.printStackTrace();
	} catch (JsonParseException e) {
		e.printStackTrace();
	} catch (IOException e) {
		e.printStackTrace();
	}
}


結構雑な箇所もありますが、ひとまず上記で使うことができました。
Data Binding が圧倒的に楽な感じですかね。


[ 環境情報 ]
Eclipse 4.2
Jackson 2.3.1 ( jackson-core-2.3.1.jar、jackson-databind-2.3.1.jar、jackson-annotations-2.3.1.jar )
※ ダウンロードは以下から。
・Index of /maven2/com/fasterxml/jackson/
http://repo1.maven.org/maven2/com/fasterxml/jackson/


以上です。