Java JSONの例

Java JSON のサンプルチュートリアルへようこそ。JSON(JavaScript Object Notation)は、人が読みやすい形式のデータを生成するためのテキストベースの軽量な技術です。JSON は、キーと値のペアの形式でオブジェクトデータを表現します。ネストされた JSON オブジェクトも持つことができ、配列も簡単に表現する方法を提供しています。

Java JSON
JavaのJSON

JSONは、XMLよりも軽量でコンパクトであるため、ウェブアプリケーションやサーバーレスポンスで広く使われています。JSONオブジェクトは読み書きが簡単であり、多くの技術がJSONオブジェクトをサポートしています。そのため、JavaのウェブサービスでJSONは非常に人気があります。JSR353はついにJava EE 7に取り込まれ、JavaのJSON処理APIとなりました。jsonpはJavaのJSON処理APIのリファレンス実装です。次の依存関係を追加することで、Mavenプロジェクトで使用することができます。

<dependency>
	<groupId>org.glassfish</groupId>
  	<artifactId>javax.json</artifactId>
  	<version>1.0.2</version>
</dependency>

もしGlassFish 4.0を使用している場合は、スコープをprovidedのままにしておくことができます。なぜなら、それは既にサーバーに含まれているからです。JSON APIはJSON処理のために2つの方法を提供しています。

    1. オブジェクトモデルAPI – DOMパーサーと似ており、小さなオブジェクトに適しています。

 

    ストリーミングAPI – StaXパーサーと似ており、メモリ全体を使用したくない大きなオブジェクトに適しています。

JavaのJSON APIのいくつかの重要なインターフェースは次のようなものがあります:

    1. javax.json.JsonReader:JSONオブジェクトまたは配列をJsonObjectに読み込むためにこれを使用することができます。JsonクラスまたはJsonReaderFactoryからJsonReaderを取得することができます。

 

    1. javax.json.JsonWriter:JSONオブジェクトを出力ストリームに書き込むためにこれを使用することができます。

 

    1. javax.json.stream.JsonParser:これはプルパーサーとして機能し、JSONオブジェクトの読み取りをストリーミングサポートします。

 

    1. javax.json.stream.JsonGenerator:ストリーミング方式でJSONオブジェクトを出力ソースに書き込むためにこれを使用することができます。

 

    1. javax.json.Json:これはJSON処理オブジェクトを作成するためのファクトリクラスです。このクラスは、これらのオブジェクトとそれに対応するファクトリの作成に最も一般的に使用されるメソッドを提供します。ファクトリクラスは、これらのオブジェクトを作成するさまざまな方法を提供します。

 

    javax.json.JsonObject:JsonObjectは不変のJSONオブジェクト値を表します。

シンプルなプログラムでJavaのJSON APIの使用方法を調べてみましょう。employee.txtというファイルにJSONオブジェクトが保存されています。

{
	"id":123,
	"name":"Pankaj Kumar",
	"permanent":true,
	"address":{
			"street":"El Camino Real",
			"city":"San Jose",
			"zipcode":95014
		},
	"phoneNumbers":[9988664422, 1234567890],
	"role":"Developer"
}

私たちは、上記のJSON形式を表すJavaのビーンクラスを持っています。

package com.scdev.model;

import java.util.Arrays;

public class Employee {

	private int id;
	private String name;
	private boolean permanent;
	private Address address;
	private long[] phoneNumbers;
	private String role;
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public boolean isPermanent() {
		return permanent;
	}
	public void setPermanent(boolean permanent) {
		this.permanent = permanent;
	}
	public Address getAddress() {
		return address;
	}
	public void setAddress(Address address) {
		this.address = address;
	}
	public long[] getPhoneNumbers() {
		return phoneNumbers;
	}
	public void setPhoneNumbers(long[] phoneNumbers) {
		this.phoneNumbers = phoneNumbers;
	}
	public String getRole() {
		return role;
	}
	public void setRole(String role) {
		this.role = role;
	}
	
	@Override
	public String toString(){
		StringBuilder sb = new StringBuilder();
		sb.append("***** Employee Details *****\n");
		sb.append("ID="+getId()+"\n");
		sb.append("Name="+getName()+"\n");
		sb.append("Permanent="+isPermanent()+"\n");
		sb.append("Role="+getRole()+"\n");
		sb.append("Phone Numbers="+Arrays.toString(getPhoneNumbers())+"\n");
		sb.append("Address="+getAddress());
		sb.append("\n*****************************");
		
		return sb.toString();
	}
}
package com.scdev.model;

public class Address {
	
	private String street;
	private String city;
	private int zipcode;
	
	public String getStreet() {
		return street;
	}
	public void setStreet(String street) {
		this.street = street;
	}
	public String getCity() {
		return city;
	}
	public void setCity(String city) {
		this.city = city;
	}
	public int getZipcode() {
		return zipcode;
	}
	public void setZipcode(int zipcode) {
		this.zipcode = zipcode;
	}
	
	@Override
	public String toString(){
		return getStreet() + ", "+getCity()+", "+getZipcode();
	}
}

私はtoString()メソッドをオーバーライドして、JSON実装クラスで使用する人が読みやすい文字列表現を返します。

JavaでJSONを読む例を示します。

package com.scdev.json;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonObject;
import javax.json.JsonReader;
import javax.json.JsonValue;

import com.scdev.model.Address;
import com.scdev.model.Employee;

public class EmployeeJSONReader {

	public static final String JSON_FILE="employee.txt";
	
	public static void main(String[] args) throws IOException {
		InputStream fis = new FileInputStream(JSON_FILE);
		
		//create JsonReader object
		JsonReader jsonReader = Json.createReader(fis);
		
		/**
		 * We can create JsonReader from Factory also
		JsonReaderFactory factory = Json.createReaderFactory(null);
		jsonReader = factory.createReader(fis);
		*/
		
		//get JsonObject from JsonReader
		JsonObject jsonObject = jsonReader.readObject();
		
		//we can close IO resource and JsonReader now
		jsonReader.close();
		fis.close();
		
		//Retrieve data from JsonObject and create Employee bean
		Employee emp = new Employee();
		
		emp.setId(jsonObject.getInt("id"));
		emp.setName(jsonObject.getString("name"));
		emp.setPermanent(jsonObject.getBoolean("permanent"));
		emp.setRole(jsonObject.getString("role"));
		
		//reading arrays from json
		JsonArray jsonArray = jsonObject.getJsonArray("phoneNumbers");
		long[] numbers = new long[jsonArray.size()];
		int index = 0;
		for(JsonValue value : jsonArray){
			numbers[index++] = Long.parseLong(value.toString());
		}
		emp.setPhoneNumbers(numbers);
		
		//reading inner object from json object
		JsonObject innerJsonObject = jsonObject.getJsonObject("address");
		Address address = new Address();
		address.setStreet(innerJsonObject.getString("street"));
		address.setCity(innerJsonObject.getString("city"));
		address.setZipcode(innerJsonObject.getInt("zipcode"));
		emp.setAddress(address);
		
		//print employee bean information
		System.out.println(emp);
		
	}

}

上記のプログラムを実行すると、以下の出力が得られます。実装はストレートで、HashMapからパラメータを取得するのと似た感覚です。JsonReaderFactoryはファクトリーデザインパターンを実装しています。

***** Employee Details *****
ID=123
Name=Pankaj Kumar
Permanent=true
Role=Developer
Phone Numbers=[9988664422, 1234567890]
Address=El Camino Real, San Jose, 95014
*****************************

JavaによるJSON書き込みの例

package com.scdev.json;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;

import javax.json.Json;
import javax.json.JsonArrayBuilder;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import javax.json.JsonWriter;

import com.scdev.model.Address;
import com.scdev.model.Employee;

public class EmployeeJSONWriter {

	public static void main(String[] args) throws FileNotFoundException {

		Employee emp = createEmployee();

		JsonObjectBuilder empBuilder = Json.createObjectBuilder();
		JsonObjectBuilder addressBuilder = Json.createObjectBuilder();
		JsonArrayBuilder phoneNumBuilder = Json.createArrayBuilder();

		for (long phone : emp.getPhoneNumbers()) {
			phoneNumBuilder.add(phone);
		}
		
		addressBuilder.add("street", emp.getAddress().getStreet())
						.add("city", emp.getAddress().getCity())
							.add("zipcode", emp.getAddress().getZipcode());
		
		empBuilder.add("id", emp.getId())
					.add("name", emp.getName())
						.add("permanent", emp.isPermanent())
							.add("role", emp.getRole());
		
		empBuilder.add("phoneNumbers", phoneNumBuilder);
		empBuilder.add("address", addressBuilder);
		
		JsonObject empJsonObject = empBuilder.build();
		
		System.out.println("Employee JSON String\n"+empJsonObject);
		
		//write to file
		OutputStream os = new FileOutputStream("emp.txt");
		JsonWriter jsonWriter = Json.createWriter(os);
		/**
		 * We can get JsonWriter from JsonWriterFactory also
		JsonWriterFactory factory = Json.createWriterFactory(null);
		jsonWriter = factory.createWriter(os);
		*/
		jsonWriter.writeObject(empJsonObject);
		jsonWriter.close();
	}
	

	public static Employee createEmployee() {

		Employee emp = new Employee();
		emp.setId(100);
		emp.setName("David");
		emp.setPermanent(false);
		emp.setPhoneNumbers(new long[] { 123456, 987654 });
		emp.setRole("Manager");

		Address add = new Address();
		add.setCity("Bangalore");
		add.setStreet("BTM 1st Stage");
		add.setZipcode(560100);
		emp.setAddress(add);

		return emp;
	}

}

上記のアプリケーションを実行すると、次のような応答を得ます。

Employee JSON String
{"id":100,"name":"David","permanent":false,"role":"Manager","phoneNumbers":[123456,987654],"address":{"street":"BTM 1st Stage","city":"Bangalore","zipcode":560100}}

JSONオブジェクトもemp.txtファイルに保存されます。JsonObjectBuilderはビルダーパターンを実装しており、非常に簡単に使用することができます。

JavaのJSONパーサーの例を示します。

JavaのJsonParserはプルパーサーであり、次の要素はnext()メソッドで読み込み、Eventオブジェクトを返します。javax.json.stream.JsonParser.Eventは列挙型であり、型安全かつ使いやすくなっています。スイッチケースでJavaのビーンのプロパティを設定することができます。

package com.scdev.json;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import javax.json.Json;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;

import com.scdev.model.Address;
import com.scdev.model.Employee;

public class EmployeeJSONParser {

	public static final String FILE_NAME = "employee.txt";

	public static void main(String[] args) throws IOException {
		InputStream fis = new FileInputStream(FILE_NAME);

		JsonParser jsonParser = Json.createParser(fis);

		/**
		 * We can create JsonParser from JsonParserFactory also with below code
		 * JsonParserFactory factory = Json.createParserFactory(null);
		 * jsonParser = factory.createParser(fis);
		 */

		Employee emp = new Employee();
		Address address = new Address();
		String keyName = null;
		List<Long> phoneNums = new ArrayList<Long>();
		
		while (jsonParser.hasNext()) {
			Event event = jsonParser.next();
			switch (event) {
			case KEY_NAME:
				keyName = jsonParser.getString();
				break;
			case VALUE_STRING:
				setStringValues(emp, address, keyName, jsonParser.getString());
				break;
			case VALUE_NUMBER:
				setNumberValues(emp, address, keyName, jsonParser.getLong(), phoneNums);
				break;
			case VALUE_FALSE:
				setBooleanValues(emp, address, keyName, false);
				break;
			case VALUE_TRUE:
				setBooleanValues(emp, address, keyName, true);
				break;
			case VALUE_NULL:
				// don't set anything
				break;
			default:
				// we are not looking for other events
			}
		}
		emp.setAddress(address);
		long[] nums = new long[phoneNums.size()];
		int index = 0;
		for(Long l :phoneNums){
			nums[index++] = l;
		}
		emp.setPhoneNumbers(nums);
		
		System.out.println(emp);
		
		//close resources
		fis.close();
		jsonParser.close();
	}

	private static void setNumberValues(Employee emp, Address address,
			String keyName, long value, List<Long> phoneNums) {
		switch(keyName){
		case "zipcode":
			address.setZipcode((int)value);
			break;
		case "id":
			emp.setId((int) value);
			break;
		case "phoneNumbers":
			phoneNums.add(value);
			break;
		default:
			System.out.println("Unknown element with key="+keyName);	
		}
	}

	private static void setBooleanValues(Employee emp, Address address,
			String key, boolean value) {
		if("permanent".equals(key)){
			emp.setPermanent(value);
		}else{
			System.out.println("Unknown element with key="+key);
		}
	}

	private static void setStringValues(Employee emp, Address address,
			String key, String value) {
		switch(key){
		case "name":
			emp.setName(value);
			break;
		case "role":
			emp.setRole(value);
			break;
		case "city":
			address.setCity(value);
			break;
		case "street":
			address.setStreet(value);
			break;
		default:
			System.out.println("Unknown Key="+key);
				
		}
	}

}

データを解析するためのロジックを書くときに、最も複雑な部分が生じます。時には複雑になることもあります。JsonReaderと同じファイルを読み込んでいるため、出力はEmployeeJsonReaderプログラムと同じです。

JavaのJsonGeneratorの例

package com.scdev.json;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import javax.json.Json;
import javax.json.stream.JsonGenerator;

import com.scdev.model.Employee;

public class EmployeeJSONGenerator {

	public static void main(String[] args) throws IOException {
		OutputStream fos = new FileOutputStream("emp_stream.txt");
		JsonGenerator jsonGenerator = Json.createGenerator(fos);
		/**
		 * We can get JsonGenerator from Factory class also
		 * JsonGeneratorFactory factory = Json.createGeneratorFactory(null);
		 * jsonGenerator = factory.createGenerator(fos);
		 */
		
		Employee emp = EmployeeJSONWriter.createEmployee();
		jsonGenerator.writeStartObject(); // {
		jsonGenerator.write("id", emp.getId()); // "id":123
		jsonGenerator.write("name", emp.getName());
		jsonGenerator.write("role", emp.getRole());
		jsonGenerator.write("permanent", emp.isPermanent());
		
		jsonGenerator.writeStartObject("address") //start of address object
			.write("street", emp.getAddress().getStreet())
			.write("city",emp.getAddress().getCity())
			.write("zipcode",emp.getAddress().getZipcode())
			.writeEnd(); //end of address object
		
		jsonGenerator.writeStartArray("phoneNumbers"); //start of phone num array
		for(long num : emp.getPhoneNumbers()){
			jsonGenerator.write(num);
		}
		jsonGenerator.writeEnd(); // end of phone num array
		jsonGenerator.writeEnd(); // }
		
		jsonGenerator.close();
		
	}

}

JsonGeneratorは非常に使いやすく、大量のデータに対して良好なパフォーマンスを提供します。これがJava JSON処理APIの全てです。私たちはJava JSONパーサー、読み込みと書き込みの例について学びました。以下のリンクからJavaプロジェクトをダウンロードして、自由に試してみてください。

JavaのJSONプロジェクトをダウンロードしてください。

参照:JSONLint – JSONデータの検証に便利なウェブツール JSON処理の参考実装 JSR353 JCPページ

コメントを残す 0

Your email address will not be published. Required fields are marked *