轉:關於如何處理JSONObject.fromObject(Object obj)無法轉換特殊日期(java.sql.Date,java.sql.Timestamp)格式的問題。
關於JSONObject的封裝,或者說使用,現在市面上很多。這里不做過多的描述,但是有種情況卻不得不說明下,JSONObject進行對對象進行JSON格式轉換,但是在轉換過程中,遇到了
Java.sql.Date類型的屬性無法完成轉換,並且拋出異常:net.sf.json.JSONException:
java.lang.reflect.InvocationTargetException
很多人遇到這個問題后,應該會查詢百度等搜索引擎,那么可能得到一種類型轉換的說法,我們也得到這樣的說法,
后來多方測試,也確實是這個問題。如何解決?
或許很多人會說,那既然時間格式無法轉換,我們可以轉換設計類型嘛,數據庫中我們不用date或datetime,直接用
varchar,而java中直接用String好了。確實這不失一個解決問題的辦法,但是如果我們不改呢?
下面是我給出的設計圖:
在這個設計圖中,我給出了一個接口JsonValueProcessor ,這個接口可以自定義一些JSON類型轉換器,正好,我就
分別定義了3種不同類型的類型轉換器。
分析上圖,我定義了3種角色:
1、類型轉換器抽象接口:分別定義了2個接口方法,一個用於處理數組,一個用於處理屬性類型;
2、類型轉換器具體實現類:實現了上述抽象接口類的接口方法;
3、調用者:用戶通過調用“調用者”的方法,完成由對象向JSONObject轉換。
類型轉換器抽象接口,由json-lib.jar提供,我們不必定義。
處理java.sql.Date類型屬性的類型轉換器:
- package com.lovo.util;
- import java.text.SimpleDateFormat;
- import java.util.Date;
- import net.sf.json.JsonConfig;
- import net.sf.json.processors.JsonValueProcessor;
- /**
- * 定義一個自己的時間適配處理器
- * @author Administrator
- *
- */
- public class SQLDateProcessor implements JsonValueProcessor{
- private String format = "yyyy-MM-dd hh:mm:ss";//自定義時間格式化的樣式
- public SQLDateProcessor() {
- super();
- // TODO Auto-generated constructor stub
- }
- public SQLDateProcessor(String format) {
- this.format = format;
- }
- public Object processArrayValue(Object arg0, JsonConfig arg1) {
- // TODO Auto-generated method stub
- return arg0;
- }
- /**
- * 處理對象的值
- * str 這個參數是當前需要處理的屬性名
- */
- public Object processObjectValue(String str, Object obj, JsonConfig arg2) {
- // TODO Auto-generated method stub
- String ret = "";
- if(obj instanceof java.sql.Date){
- SimpleDateFormat sdf = new SimpleDateFormat(format);
- ret = sdf.format(new Date(((java.sql.Date) obj).getTime()));
- }
- return ret;
- }
- }
處理java.util.Date類型的類型轉換器:
- package com.lovo.util;
- import java.text.SimpleDateFormat;
- import java.util.Date;
- import net.sf.json.JsonConfig;
- import net.sf.json.processors.JsonValueProcessor;
- /**
- * 定義一個自己的時間適配處理器
- * @author Administrator
- *
- */
- public class UtilDateProcessor implements JsonValueProcessor{
- private String format = "yyyy-MM-dd hh:mm:ss";//自定義時間格式化的樣式
- public UtilDateProcessor() {
- super();
- // TODO Auto-generated constructor stub
- }
- public UtilDateProcessor(String format) {
- this.format = format;
- }
- public Object processArrayValue(Object arg0, JsonConfig arg1) {
- // TODO Auto-generated method stub
- return arg0;
- }
- /**
- * 處理對象的值
- * str 這個參數是當前需要處理的屬性名
- */
- public Object processObjectValue(String str, Object obj, JsonConfig arg2) {
- // TODO Auto-generated method stub
- String ret = "";
- if(obj instanceof java.util.Date){
- SimpleDateFormat sdf = new SimpleDateFormat(format);
- ret = sdf.format(((Date) obj).getTime());
- }
- return ret;
- }
- }
處理java.sql.Timestamp類型的類型轉換器:
- package com.lovo.util;
- import java.text.SimpleDateFormat;
- import java.util.Date;
- import net.sf.json.JsonConfig;
- import net.sf.json.processors.JsonValueProcessor;
- /**
- * 定義一個自己的時間適配處理器
- * @author Administrator
- *
- */
- public class TimestampProcessor implements JsonValueProcessor{
- private String format = "yyyy-MM-dd hh:mm:ss";//自定義時間格式化的樣式
- public TimestampProcessor() {
- super();
- // TODO Auto-generated constructor stub
- }
- public TimestampProcessor(String format) {
- this.format = format;
- }
- public Object processArrayValue(Object arg0, JsonConfig arg1) {
- // TODO Auto-generated method stub
- return arg0;
- }
- /**
- * 處理對象的值
- * str 這個參數是當前需要處理的屬性名
- */
- public Object processObjectValue(String str, Object obj, JsonConfig arg2) {
- // TODO Auto-generated method stub
- String ret = "";
- if(obj instanceof java.sql.Timestamp){
- SimpleDateFormat sdf = new SimpleDateFormat(format);
- ret = sdf.format(((Date) obj).getTime());
- }
- return ret;
- }
- }
調用者類:
- package com.lovo.util;
- import java.util.Iterator;
- import java.util.Map;
- import net.sf.json.JSONObject;
- import net.sf.json.JsonConfig;
- import net.sf.json.processors.JsonValueProcessor;
- /**
- * JSON格式轉換類
- * @author Administrator
- *
- */
- public class JSONUtil {
- /**
- * 將一個對象直接轉換為一個JSONObject對象,
- * 同樣適合於JSON格式的字符串
- * 但是如果存在java.sql.Date或者java.sql.Timestamp時間格式,調用例外一個toJson轉換方法
- * @param obj
- * @return
- */
- public static JSONObject toJson(Object obj) {
- return JSONObject.fromObject(obj);
- }
- /**
- *
- * @param obj 需要轉換的參數
- * @param processors 類型轉換器的集合,參數是一個Map集合,鍵代表需要轉換類型的全路徑,值是類型轉換器
- * @return
- * @throws ClassNotFoundException
- */
- public static JSONObject toJson(Object obj,Map<String,JsonValueProcessor> processors) throws ClassNotFoundException{
- //定義一個JSONConfig對象,該對象可以制定一個轉換規則
- JsonConfig config = new JsonConfig();
- if(processors != null && !processors.isEmpty()){
- Iterator<java.util.Map.Entry<String, JsonValueProcessor>> it = processors.entrySet().iterator();
- while (it.hasNext()) {
- Map.Entry<java.lang.String, net.sf.json.processors.JsonValueProcessor> entry = (Map.Entry<java.lang.String, net.sf.json.processors.JsonValueProcessor>) it
- .next();
- String key = entry.getKey();
- JsonValueProcessor processor = processors.get(key);
- //反射獲取到需要轉換的類型
- Class<?> cls = Class.forName(key);
- config.registerJsonValueProcessor(cls, processor);
- }
- }
- return JSONObject.fromObject(obj, config);
- }
- }
客戶端調用“調用者”類,來完成對象向JSONObject進行轉換:
- package com.test.util;
- import java.sql.Date;
- import java.sql.Timestamp;
- import java.util.HashMap;
- import java.util.Map;
- import org.junit.Ignore;
- import org.junit.Test;
- import com.lovo.util.SQLDateProcessor;
- import com.lovo.util.JSONUtil;
- import com.lovo.util.TimestampProcessor;
- import com.lovo.util.User;
- import net.sf.json.JSONObject;
- import net.sf.json.processors.JsonValueProcessor;
- public class JSONTest {
- @Test
- public void testJsonObjectOne() {
- String shortFormat = "yyyy-MM-dd";
- String longFormat = "yyyy-MM-dd hh:mm:ss";
- Date sqlDate = new Date(System.currentTimeMillis());
- Timestamp createTime = new Timestamp(System.currentTimeMillis());
- User user = new User("高高", sqlDate, createTime);
- // 定義一個類型轉化器集合,鍵是需要轉換的類型全路徑,值是用於轉換的類型轉換器
- Map<String, JsonValueProcessor> processors = new HashMap<String, JsonValueProcessor>();
- //有了2-3種時間轉換器,那么我們設計時,就可以短時間格式用Date,長時間格式就是用Timestamp
- processors.put("java.sql.Date", new SQLDateProcessor(shortFormat));
- // processors.put("java.util.Date", new UtilDateProcessor(shortFormat));
- processors.put("java.sql.Timestamp", new TimestampProcessor(longFormat));
- JSONObject json = null;
- try {
- json = JSONUtil.toJson(user, processors);
- } catch (ClassNotFoundException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- System.out.println(json.toString());
- }
- /**
- * 將一個JSON格式的字符串轉換為JSONObject對象,並獲得其值
- */
- @Ignore
- public void testJsonObjectTwo() {
- // {"createTime":"2016-06-03 04:05:23","birthday":"2016-06-03","name":"高高"}
- String str = "{'createTime':'2016-06-03 04:05:23','birthday':'2016-06-03','name':'1'}";
- JSONObject json = null;
- try {
- json = JSONUtil.toJson(str, null);
- } catch (ClassNotFoundException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- System.out.println(json.get("name"));
- System.out.println(json.get("createTime"));
- System.out.println(json.get("birthday"));
- }
- }
得到的結果是:
- {"createTime":"2016-06-03 05:09:49","birthday":"2016-06-03","name":"高高"}
在JSONUtil類中,由於我們可以采用JSONConfig類來一次性注冊多個類型轉換器,所以我將多個類型轉換器裝配到
Map中,迭代Map集合采用反射機制來獲取到需要轉換的類型,向JSONConfig類中注冊。
在這個過程中,封裝了日期格式的傳遞,方便大家得到自己想要的日期格式。