【Java】JSON-libを使ってJSON配列を生成する際に日付型(Date)を好きなフォーマットで変換する方法

Java,開発

おはようございます。

最近はWEBのサービス開発などでSPA(Single Page Applicatoin)が流行って?るので、
サーバーとクライアントとのデータのやり取りをJSONで行うのはよくあるケースかと思います。

サーバー側をJavaで開発している場合に、Javaオブジェクトや Bean を JSONに変換するのに、
JSON-lib というのも結構主流なやり方かと思いますが、ちょっと日付型のところでハマったので備忘的な記事を。

※JSON-lib 自体の詳しい説明(利用方法)などは省略します。

スポンサーリンク

JSON-libとは

OSDNサイトより転載

Json-libは、beans, map, collection, Java配列、XML to JSON, DynaBeansを変革するJavaライブラリです。 Douglas Crockfordによる作業をベースにしています。

Javaオブジェクトを簡単に JSON文字列に変換したり、逆に JSON文字列からオブジェクトを生成したりといったことが可能です。

昔、XMLへの相互変換ロジックを自作したことがありますが、こういう処理って実際に作ってみると結構大変だったりします。
便利な世の中ですね。

サンプル

変換するサンプルクラスを作成。

Person.java

package jp.co.doraxdora.sample;

import java.io.Serializable;
import java.util.Date;

/**
 * パーソンクラス
 *
 * @author doraxdora
 *
 */
public class Person implements Serializable {

	/** ID */
	private int id;
	/** 氏名 */
	private String name;
	/** 年齢 */
	private int age;
	/** 更新日時 */
	private Date updateDate;

	public Person() {
	}

	/**
	 * パーソンの生成
	 *
	 * @param id
	 * @param name
	 * @param age
	 */
	public Person(int id, String name, int age, Date updateDate) {
		this.id = id;
		this.name = name;
		this.age = age;
		this.updateDate = updateDate;
	}

	/**
	 * @return id
	 */
	public int getId() {
		return id;
	}

	/**
	 * @param id セットする id
	 */
	public void setId(int id) {
		this.id = id;
	}

	/**
	 * @return name
	 */
	public String getName() {
		return name;
	}

	/**
	 * @param name セットする name
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * @return age
	 */
	public int getAge() {
		return age;
	}

	/**
	 * @param age セットする age
	 */
	public void setAge(int age) {
		this.age = age;
	}

	/**
	 * @return updateDate
	 */
	public Date getUpdateDate() {
		return updateDate;
	}

	/**
	 * @param updateDate セットする updateDate
	 */
	public void setUpdateDate(Date updateDate) {
		this.updateDate = updateDate;
	}

}

何故か更新日時を持つパーソンクラスです。

JavaオブジェクトからJSON文字列に変換

import net.sf.json.JSONObject;

public class HelloWorld {
    public static void main(String[] args) {

		Person person = new Person(1, "サンプル 一郎", 20, new Date());

		JSONObject jsonObject = JSONObject.fromObject(person);
		System.out.println(String.valueOf(jsonObject));
    }
}

こんな感じで、Dateを持つクラスをJSONに変換すると次のような文字列が生成されます。

{
	"age": 20,
	"id": 1,
	"name": "サンプル 一郎",
	"updateDate": {
		"date": 23,
		"day": 2,
		"hours": 10,
		"minutes": 22,
		"month": 3,
		"seconds": 44,
		"time": 1555982564167,
		"timezoneOffset": -540,
		"year": 119
	}
}

これはこれで正しいのですが、クライアント側で日時の部分が扱いづらい。。

対応

JSON-lib には、「JsonValueProcessor」という、変換時に対象となる値に対して処理できるインターフェースが定義されているので、
実装したクラスを作成して日付型オブジェクトに対して別途変換する処理を組み込みます。

DateJsonValueProcessor.java

package jp.co.doraxdora.sample;

import java.util.Date;

import net.sf.json.JsonConfig;
import net.sf.json.processors.JsonValueProcessor;
import java.text.SimpleDateFormat;

/**
 * 日付型をJSON変換する際にフォーマットする
 *
 * @author doraxdora
 *
 */
public class DateJsonValueProcessor implements JsonValueProcessor {

	/* (非 Javadoc)
	 * @see net.sf.json.processors.JsonValueProcessor#processArrayValue(java.lang.Object, net.sf.json.JsonConfig)
	 */
	@Override
	public Object processArrayValue(Object value, JsonConfig jsonConfig) {
		return process((Date) value, jsonConfig);
	}

	/* (非 Javadoc)
	 * @see net.sf.json.processors.JsonValueProcessor#processObjectValue(java.lang.String, java.lang.Object, net.sf.json.JsonConfig)
	 */
	@Override
	public Object processObjectValue(String key, Object value, JsonConfig jsonConfig) {
		return process((Date) value, jsonConfig);
	}

	/**
	 * 日付型を文字列に変換.
	 *
	 * @param date
	 * @param config
	 * @return
	 */
	private Object process(Date date, JsonConfig config) {
		if (date == null) {
			return null;
		}
		
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd(E)");
		
		return formatter.format(date);
	}

}

JsonConfig に DateValueProcessor を設定して変換

import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;

public class HelloWorld {
    public static void main(String[] args) {

		Person person = new Person(1, "サンプル 一郎", 20, new Date());

		JsonConfig config = new JsonConfig();
		config.registerJsonValueProcessor(java.util.Date.class, new DateJsonValueProcessor());

		JSONObject jsonObject = JSONObject.fromObject(person, config);
		System.out.println(String.valueOf(jsonObject));
    }
}

という感じで、日付型だった場合の処理を設定して変換してあげると次のような文字列が生成されます。

{
	"age": 20,
	"id": 1,
	"name": "サンプル 一郎",
	"updateDate": "2019/04/23(火)"
}

大分シンプルになりました。

まとめ

ちょっとした単発のプログラムネタでした。

実は以前 Python でも同様の問題にぶち当たったことがあって、
だったら Java でも同じようになんとかできるだろうと調べてみたという感じです。

何かのお役に立てれば。

ではでは。

 

スポンサーリンク


関連するコンテンツ