由於JSON資料格式的諸多優點,現在就資料轉送這個方面已經完勝XML,成為當下比較流行資料轉送格式。所以越來越多的項目採用了這種格式進行前後台資料的傳送。咱公司後台主要用的是java平台相關的技術,因此在JSON字串格式與java對象格式的轉換上成為了我們平常經常要做的工作。這裡給大家分享一下採用JSON-lib來轉換JSON字串與java對象的相關經驗。
(一)java對象轉換為JSON字串。
這種情況用碰到的比較多的就是一個指定的java對象轉換為期待的字串格式。比如說Calendar轉換為“yyyy-MM-dd HH:mm:ss”格式的字串,或是Date轉換為“yyyy-MM-dd HH:mm:ss”格式的字串等。此處以Calendar為例說明一下轉換方法。
//轉換方法
public static String Object2JSONString(Object object) {
if (object == null) {
return null;
}
JsonConfig jsonConfig = new JsonConfig();
jsonConfig.registerJsonValueProcessor(Calendar.class, new CalendarJsonValueProcessor());
JSON jsonObject = JSONSerializer.toJSON(object,jsonConfig);
return jsonObject == null ? null :jsonObject.toString();
}
//定義轉換所用到的內部類
private static class CalendarJsonValueProcessor implements JsonValueProcessor{
SimpleDateFormat dateFormat = new SimpleDateFormat(TaskEngineConstants.LOG_DATE_FORMAT);
@Override
public Object processArrayValue(Objectobj, JsonConfig jsonconfig){
if (obj == null){
return null;
}
return dateFormat.format(((Calendar)obj).getTime());
}
@Override
public ObjectprocessObjectValue(String s, Object obj, JsonConfig jsonconfig) {
if (obj == null){
return null;
}
return dateFormat.format(((Calendar)obj).getTime());
}
}
(二)JSON字串轉換為java對象。
在要轉換的java比較簡單的時候,基本上都能順利轉換。下面介紹一種比較特別的情況,也是我們在項目中所碰到的情況。
有一個WSDL的對象HotelBookingInfo, 內有子物件AgeGroup, 它是Axis2產生的一個在WSDL中表示多選一的java類,實際在java中,一般多選一都用枚舉。但此處的AgeGroup並非為enum, 而是一個沒有public建構函式的class, 如果你要執行個體化的話可採用AgeGroup.Factory.fromValue(value)方法(Axis2自動產生)。因為在JSON-lib轉換字串為java對象的時候,每碰到java對象的內部屬性為新的對象的時候都會先調用其預設的public的建構函式還構造這個對象,再填儲值。故在轉換的時候如果不做任何處理,轉換會失敗,報找不到AgeGourp類public構造方法的錯誤。
解決辦法如下:
//轉換方法
public static String JSONString2Object(String jsonString){
JSONObject jsonObject = JSONObject.fromObject(jsonString);
// the key point is below
JsonConfig jsonConfig = new JsonConfig();
jsonConfig.setNewBeanInstanceStrategy(new HotelNewBeanInstanceStrategy());
jsonConfig.setRootClass(HotelBookingInfo.class);
HotelBookingInfo info = (HotelBookingInfo) JSONObject.toBean(jsonObject,jsonConfig);
}
// 定義內部類用來修改預設的物件建構方式
public static class HotelNewBeanInstanceStrategy extends NewBeanInstanceStrategy {
@Override
public Object newInstance(Classc, JSONObject jo) throws InstantiationException,
IllegalAccessException,SecurityException, NoSuchMethodException, InvocationTargetException {
Object o;
if(c.equals(AddressType.class)) {
String t = jo.get("value").toString();
o = AddressType.Factory.fromValue(t);
}
else if (c.equals(AgeGroup.class)) {
String t = jo.get("value").toString();
o = AgeGroup.Factory.fromValue(t);
}
else {
o = c.newInstance();
}
return o;
}
}
同時在這裡還有一個要注意的是JSONObject.toBean(jsonObject, jsonConfig)方法有一個重載方法JSONObject.toBean(jsonObject,HotelBookingInfo.class, jsonConfig)。
如果你使用的是如下代碼
JSONObject jsonObject = JSONObject.fromObject(dto.getReservationDetails());
// convert detail to info.
JsonConfig jsonConfig = new JsonConfig();
jsonConfig.setNewBeanInstanceStrategy(newHotelNewBeanInstanceStrategy());
HotelBookingInfo info = (HotelBookingInfo)JSONObject.toBean(jsonObject, HotelBookingInfo.class, jsonConfig);
看起來和上面的寫法差不多,但是這種方式下會拋異常(java.lang.ClassCastException: java.lang.Class cannot be cast tocom.telenav.ws.datatypes.hotel.v10.HotelBookingInfo)。於是反編譯了一下代碼,發現兩個重載方法是各自寫的實現,表面上得出結果應該是一樣的,但是事實上這種做法存在上述問題,記得以前也碰到過。所以大家注意一下類似問題。