在我們android的日常開發中,經常會遇到,把一個數據類轉成JSON,然後把JSON當作參數與網絡進行通訊,還有就是從後臺獲取回來的數據是JSON,而使用數據時傳遞或者保存到手機本地數據庫往往是數據類,這時爲了以後容易維護,就需要把JSON轉成數據類,這樣以後即使需求變了,把數據類的成員變量修改了,也容易維護,不至於每個地方都需要修改,萬一漏修改了某個地方,那麼的話就會出錯,所以本篇文章就是介紹數據類與JSON的互相轉換。我找了很久,最後發現還是google牛逼,已經實現了這樣需求,它的描述如下:A Java serialization library that can convert Java Objects into JSONand back.(這是一個把對象轉成JSON又轉回來的Java序列化庫)
我自己也在使用,很好用,所以推薦給大家,它的源碼地址:https://github.com/google/gson
可以去下載下來,可以把關鍵源碼直接導入到自己的項目中,也可以打包後導入。
下面我就來講講它使用:
1. 數據類轉成JSON
private JSONObject getJSONByOBj(UserInfo aUserInfo){
Gson gson = new Gson();
String jsnStr=gson.toJson(aUserInfo);
JSONObject jsonObject=null;
try {
jsonObject= new JSONObject(jsnStr);
}catch (Exception e){
e.printStackTrace();
}
return jsonObject;
}
呵呵,看到了吧,很簡單!
2. JSON轉成數據類
Gson gson = new Gson();
try {
UserInfouserInfo=gson.fromJson("JSON數據",UserInfo.class);
//做你想做的事情。。
}catch (Exception e){
e.printStackTrace();
}
關於json轉成數據類,我在網上還找到一種辦法,現在共享給大家:
/**
* 反序列化簡單對象
* @param jo json對象
* @param clazz 實體類類型
* @return 反序列化後的實例
* @throws JSONException
*/
publicstatic <T> T parseObject(JSONObject jo, Class<T> clazz) throwsJSONException {
if(clazz == null || isNull(jo)) {
returnnull;
}
Tobj = newInstance(clazz);
if(obj == null) {
returnnull;
}
if(isMap(clazz)){
setField(obj,jo);
}else{
//取出bean裏的所有方法
Method[]methods = clazz.getDeclaredMethods();
Field[]fields = clazz.getDeclaredFields();
for(Field f : fields) {
StringsetMetodName = parseMethodName(f.getName(),"set");
if(!haveMethod(methods, setMetodName)) {
continue;
}
try{
MethodfieldMethod = clazz.getMethod(setMetodName, f.getType());
setField(obj,fieldMethod,f,jo);
}catch (Exception e) {
e.printStackTrace();
}
}
}
returnobj;
}
下面我上面那個函數引用的函數:
/**
* 判斷對象是否爲空
* @param obj 實例
* @return
*/
privatestatic boolean isNull(Object obj) {
if(obj instanceof JSONObject) {
returnJSONObject.NULL.equals(obj);
}
returnobj == null;
}
/**
* 根據類型創建對象
* @param clazz 待創建實例的類型
* @return 實例對象
* @throws JSONException
*/
@SuppressWarnings({"unchecked", "rawtypes" })
privatestatic <T> T newInstance(Class<T> clazz) throws JSONException {
if(clazz == null)
returnnull;
Tobj = null;
if(clazz.isInterface()) {
if(clazz.equals(Map.class)) {
obj= (T) new HashMap();
}elseif (clazz.equals(List.class)) {
obj= (T) new ArrayList();
}elseif (clazz.equals(Set.class)) {
obj= (T) new HashSet();
}else{
thrownew JSONException("unknown interface: " + clazz);
}
}else{
try{
obj= clazz.newInstance();
}catch(Exception e) {
thrownew JSONException("unknown class type: " + clazz);
}
}
returnobj;
}
/**
* 設定Map的值
* @param obj 待賦值字段的對象
* @param jo json實例
*/
privatestatic void setField(Object obj, JSONObject jo) {
try{
@SuppressWarnings("unchecked")
Iterator<String>keyIter = jo.keys();
Stringkey;
Objectvalue;
@SuppressWarnings("unchecked")
Map<String,Object> valueMap = (Map<String, Object>) obj;
while(keyIter.hasNext()) {
key= (String) keyIter.next();
value= jo.get(key);
valueMap.put(key,value);
}
}catch (JSONException e) {
e.printStackTrace();
}
}
/**
* 拼接某屬性的 get或者set方法
* @param fieldName 字段名稱
* @param methodType 方法類型
* @return 方法名稱
*/
publicstatic String parseMethodName(String fieldName,String methodType) {
if(null == fieldName || "".equals(fieldName)) {
return null;
}
returnmethodType + fieldName.substring(0, 1).toUpperCase() +fieldName.substring(1);
}
/**
* 判斷是否存在某屬性的 get方法
* @param methods 引用方法的數組
* @param fieldMethod 方法名稱
* @return true或者false
*/
publicstatic boolean haveMethod(Method[] methods, String fieldMethod) {
for(Method met : methods) {
if(fieldMethod.equals(met.getName())) {
returntrue;
}
}
returnfalse;
}
/**
* 設定字段的值
* @param obj 待賦值字段的對象
* @param fieldSetMethod 字段方法名
* @param field 字段
* @param jo json實例
*/
privatestatic void setField(Object obj, Method fieldSetMethod,Field field, JSONObjectjo) {
Stringname = field.getName();
Class<?>clazz = field.getType();
try{
if(isArray(clazz)) { // 數組
Class<?>c = clazz.getComponentType();
JSONArrayja = jo.optJSONArray(name);
if(!isNull(ja)) {
Objectarray = parseArray(ja, c);
setFiedlValue(obj,fieldSetMethod, clazz.getSimpleName(), array);
}
}else if (isCollection(clazz)) { // 泛型集合
//獲取定義的泛型類型
Class<?>c = null;
TypegType = field.getGenericType();
if(gType instanceof ParameterizedType) {
ParameterizedTypeptype = (ParameterizedType) gType;
Type[]targs = ptype.getActualTypeArguments();
if(targs != null && targs.length > 0) {
Typet = targs[0];
c= (Class<?>) t;
}
}
JSONArrayja = jo.optJSONArray(name);
if(!isNull(ja)) {
Objecto = parseCollection(ja, clazz, c);
setFiedlValue(obj,fieldSetMethod, clazz.getSimpleName(), o);
}
}else if (isSingle(clazz)) { // 值類型
Objecto = jo.opt(name);
if(o != null) {
setFiedlValue(obj,fieldSetMethod, clazz.getSimpleName(), o);
}
}else if (isObject(clazz)) { // 對象
JSONObjectj = jo.optJSONObject(name);
if(!isNull(j)) {
Objecto = parseObject(j, clazz);
setFiedlValue(obj,fieldSetMethod, clazz.getSimpleName(), o);
}
}else if (isList(clazz)) { // 列表
// JSONObjectj = jo.optJSONObject(name);
// if(!isNull(j)) {
// Objecto = parseObject(j, clazz);
// f.set(obj,o);
// }
}else {
thrownew Exception("unknow type!");
}
}catch (Exception e) {
e.printStackTrace();
}
}
/**
* 給對象的字段賦值
* @param obj 類實例
* @param fieldSetMethod 字段方法
* @param fieldType 字段類型
* @param value
*/
publicstatic void setFiedlValue(Object obj,Method fieldSetMethod,StringfieldType,Object value){
try{
if(null != value && !"".equals(value)) {
if("String".equals(fieldType)) {
fieldSetMethod.invoke(obj,value.toString());
}else if ("Date".equals(fieldType)) {
SimpleDateFormatsdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss",Locale.CHINA);
Datetemp = sdf.parse(value.toString());
fieldSetMethod.invoke(obj,temp);
}else if ("Integer".equals(fieldType)
||"int".equals(fieldType)) {
Integerintval = Integer.parseInt(value.toString());
fieldSetMethod.invoke(obj,intval);
}else if ("Long".equalsIgnoreCase(fieldType)) {
Longtemp = Long.parseLong(value.toString());
fieldSetMethod.invoke(obj,temp);
}else if ("Double".equalsIgnoreCase(fieldType)) {
Doubletemp = Double.parseDouble(value.toString());
fieldSetMethod.invoke(obj,temp);
}else if ("Boolean".equalsIgnoreCase(fieldType)) {
Booleantemp = Boolean.parseBoolean(value.toString());
fieldSetMethod.invoke(obj,temp);
}else {
fieldSetMethod.invoke(obj,value);
Log.e(TAG,TAG +">>>>setFiedlValue -> not supper type" + fieldType);
}
}
}catch (Exception e) {
// Log.e(TAG, TAG +">>>>>>>>>>set value error.",e);
e.printStackTrace();
}
}
/**
* 判斷是否是Map
* @param clazz
* @return
*/
publicstatic boolean isMap(Class<?> clazz) {
returnclazz != null && Map.class.isAssignableFrom(clazz);
}
/**
* 判斷是否是數組
* @param clazz
* @return
*/
publicstatic boolean isArray(Class<?> clazz) {
returnclazz != null && clazz.isArray();
}
/**
* 判斷是否是集合
* @param clazz
* @return
*/
publicstatic boolean isCollection(Class<?> clazz) {
returnclazz != null && Collection.class.isAssignableFrom(clazz);
}
/**
* 判斷是否是值類型
* @param clazz
* @return
*/
privatestatic boolean isSingle(Class<?> clazz) {
returnisBoolean(clazz) || isNumber(clazz) || isString(clazz);
}
/**
* 判斷是否是對象
* @param clazz
* @return
*/
privatestatic boolean isObject(Class<?> clazz) {
returnclazz != null && !isSingle(clazz) && !isArray(clazz) &&!isCollection(clazz)&& !isMap(clazz);
}
/**
* 判斷是否是列表
* @param clazz
* @return
*/
publicstatic boolean isList(Class<?> clazz) {
returnclazz != null && List.class.isAssignableFrom(clazz);
}
/**
* 是否布爾值
* @param clazz
* @return
*/
publicstatic boolean isBoolean(Class<?> clazz) {
return(clazz != null)
&&((Boolean.TYPE.isAssignableFrom(clazz)) || (Boolean.class
.isAssignableFrom(clazz)));
}
/**
* 是否數值
* @param clazz
* @return
*/
publicstatic boolean isNumber(Class<?> clazz) {
return(clazz != null)
&&((Byte.TYPE.isAssignableFrom(clazz)) || (Short.TYPE.isAssignableFrom(clazz))
||(Integer.TYPE.isAssignableFrom(clazz))
||(Long.TYPE.isAssignableFrom(clazz))
||(Float.TYPE.isAssignableFrom(clazz))
||(Double.TYPE.isAssignableFrom(clazz)) || (Number.class
.isAssignableFrom(clazz)));
}
/**
* 判斷是否是字符串
* @param clazz
* @return
*/
publicstatic boolean isString(Class<?> clazz) {
return(clazz != null)
&&((String.class.isAssignableFrom(clazz))
||(Character.TYPE.isAssignableFrom(clazz)) || (Character.class
.isAssignableFrom(clazz)));
}
因爲文章寫的匆忙,可能有很多不足之處,請大家批評指正,如果有哥們,看了之後還有看不到的話,就在下面回覆吧,要是比較多的人需要,我也可以多花點時間寫個demo出來,這樣就可以直接運行調試了,謝謝大家!