Json(JavaScript Object Notation)是一种轻量级的数据交换格式,类似XML,但比XML更小更快更容易解析。当前各种流行的web应用框架都对Json提供良好的支持,各种流行开发语言也支持Json解析。

 

Java中解析Json的方式也很多,根据官方的JSONObject库,自己设计的一个抽象工具类:

 

Java代码  

  1. import java.io.Serializable;  

  2. import java.util.List;  

  3.   

  4. import org.json.JSONException;  

  5. import org.json.JSONObject;  

  6.   

  7. public abstract class JsonParser <T extends Serializable>{  

  8.       

  9.     abstract List<T> getListFromJson(String str);  

  10.       

  11.     abstract T getObjectFromJson(JSONObject jobj);  

  12.       

  13.     public T getObjectFromJson(String str) {  

  14.         try {  

  15.             JSONObject jsonObject = new JSONObject(str);  

  16.             return getObjectFromJson(jsonObject);  

  17.         } catch (JSONException e) {  

  18.             e.printStackTrace();   

  19.         } catch(Exception e){  

  20.             e.printStackTrace();  

  21.         }  

  22.         return null;  

  23.     }  

  24.       

  25.     protected String getValueByName(JSONObject jobj, String name)  

  26.             throws JSONException{  

  27.         if(jobj.has(name)){  

  28.             return jobj.getString(name);  

  29.         }  

  30.         return null;  

  31.     }  

  32.       

  33. }  

 

具体实现的子类如下:

 

Java代码  

  1. public class UserInfoParser extends JsonParser<UserInfo> {  

  2.   

  3.     private UserInfoParser() {  

  4.           

  5.     }  

  6.       

  7.     @Override  

  8.     List<UserInfo> getListFromJson(String str) {  

  9.         try {  

  10.             JSONArray array = new JSONArray(str);  

  11.             int len = array.length();  

  12.             ArrayList<UserInfo> list = new ArrayList<UserInfo>(len);  

  13.             for(int i=0;i<len;i++) {  

  14.                 UserInfo info = getObjectFromJson(array.getJSONObject(i));  

  15.                 list.add(info);  

  16.             }  

  17.             return list;  

  18.         } catch (JSONException e) {  

  19.             e.printStackTrace();  

  20.         }  

  21.         return null;  

  22.     }  

  23.   

  24.     @Override  

  25.     UserInfo getObjectFromJson(JSONObject jobj) {  

  26.         try {  

  27.             UserInfo info = new UserInfo();  

  28.             info.setId(getValueByName(jobj, UserInfo.NODE_ID));  

  29.             info.setFace(getValueByName(jobj,UserInfo.NODE_FACE));  

  30.             info.setUsername(getValueByName(jobj,UserInfo.NODE_USER_NAME));  

  31.             return info;  

  32.         } catch (JSONException e) {  

  33.             e.printStackTrace();  

  34.         }  

  35.         return null;  

  36.     }  

  37.   

  38. }  

 

当泛型值对象T,对应的数据结构比较简单,层次比较少的时候,官方的JSONObject库解析还过得去。当遇到层次较多(Json里面包含N个Json数组),数据结构复杂(Json由对个复杂数据的Json组成)的Json,解析速度就会大大降低!

 

在处理复杂Json结构时,我推荐使用Google的Gson解析库。刚刚接触Gson时,我有以下疑虑:

1、Gson对Json的支持度如何,能不能支持所有的Json结构?

2、由于Gson是基于Java的反射原理来实现的,解析的效率如何保证?

3、上手难度如何?

 

当我在项目实验性地引入Gson后,我o嘴了~~真不愧是Google出品,实属佳品!

 

再我的项目是基于android平台的App,使用Gson之前,不仅http请求和Json数据解析的耗时太长,而且内存占有一直居高不下。

使用Gson后,解析的时间缩短了30%(这只是Json的解析时间,不算上http请求的时间),内存占用足足减少了一半!!!最重要的是,开发效率还提高不少,何以见得,请看:

 

1、值对象必须实现序列化接口,成员属性的名称必须与Json数据的key一致,建议遵从J2EE的标准,使用get-set方法控制属性的访问,因为Json的key是后台应用定义的,假如后台与前台的开发语言不同,命名规范也不一致,使用get-set能有效分离这些不规范的命名到其他模块代码中去。

 

 

Java代码  

  1. public class UserInfo implements Serializable {  

  2.   

  3.     private static final long serialVersionUID = 1050128890144400614L;  

  4.   

  5.     private String id;  

  6.     private String username;  

  7.     private String face;  

  8.   

  9.     public String getId() {  

  10.         return id;  

  11.     }  

  12.   

  13.     public void setId(String id) {  

  14.         this.id = id;  

  15.     }  

  16.   

  17.     public String getUsername() {  

  18.         return username;  

  19.     }  

  20.   

  21.     public void setUsername(String username) {  

  22.         this.username = username;  

  23.     }  

  24.   

  25.     public String getFace() {  

  26.         return face;  

  27.     }  

  28.   

  29.     public void setFace(String face) {  

  30.         this.face = face;  

  31.     }  

  32.   

  33. }  

 

 

2、奉上一个基于Gson的Json解析封装工具:

 

Java代码  

  1. /** 

  2.  * Gson类库的封装工具类,专门负责解析json数据</br> 

  3.  * 内部实现了Gson对象的单例 

  4.  * @author zhiweiofli 

  5.  * @version 1.0 

  6.  * @since 2012-9-18 

  7.  */  

  8. public class JsonUtil {  

  9.   

  10.     private static Gson gson = null;  

  11.       

  12.     static {  

  13.         if (gson == null) {  

  14.             gson = new Gson();  

  15.         }  

  16.     }  

  17.   

  18.     private JsonUtil() {  

  19.       

  20.     }  

  21.   

  22.     /** 

  23.      * 将对象转换成json格式 

  24.      *  

  25.      * @param ts 

  26.      * @return 

  27.      */  

  28.     public static String objectToJson(Object ts) {  

  29.         String jsonStr = null;  

  30.         if (gson != null) {  

  31.             jsonStr = gson.toJson(ts);  

  32.         }  

  33.         return jsonStr;  

  34.     }  

  35.   

  36.     /** 

  37.      * 将对象转换成json格式(并自定义日期格式) 

  38.      *  

  39.      * @param ts 

  40.      * @return 

  41.      */  

  42.     public static String objectToJsonDateSerializer(Object ts,  

  43.             final String dateformat) {  

  44.         String jsonStr = null;  

  45.         gson = new GsonBuilder()  

  46.                 .registerTypeHierarchyAdapter(Date.class,  

  47.                         new JsonSerializer<Date>() {  

  48.                             public JsonElement serialize(Date src,  

  49.                                     Type typeOfSrc,  

  50.                                     JsonSerializationContext context) {  

  51.                                 SimpleDateFormat format = new SimpleDateFormat(  

  52.                                         dateformat);  

  53.                                 return new JsonPrimitive(format.format(src));  

  54.                             }  

  55.                         }).setDateFormat(dateformat).create();  

  56.         if (gson != null) {  

  57.             jsonStr = gson.toJson(ts);  

  58.         }  

  59.         return jsonStr;  

  60.     }  

  61.   

  62.     /** 

  63.      * 将json格式转换成list对象 

  64.      *  

  65.      * @param jsonStr 

  66.      * @return 

  67.      */  

  68.     public static List<?> jsonToList(String jsonStr) {  

  69.         List<?> objList = null;  

  70.         if (gson != null) {  

  71.             java.lang.reflect.Type type = new com.google.gson.reflect.TypeToken<List<?>>() {  

  72.             }.getType();  

  73.             objList = gson.fromJson(jsonStr, type);  

  74.         }  

  75.         return objList;  

  76.     }  

  77.       

  78.     /** 

  79.      * 将json格式转换成list对象,并准确指定类型 

  80.      * @param jsonStr 

  81.      * @param type 

  82.      * @return 

  83.      */  

  84.     public static List<?> jsonToList(String jsonStr, java.lang.reflect.Type type) {  

  85.         List<?> objList = null;  

  86.         if (gson != null) {  

  87.             objList = gson.fromJson(jsonStr, type);  

  88.         }  

  89.         return objList;  

  90.     }  

  91.   

  92.     /** 

  93.      * 将json格式转换成map对象 

  94.      *  

  95.      * @param jsonStr 

  96.      * @return 

  97.      */  

  98.     public static Map<?, ?> jsonToMap(String jsonStr) {  

  99.         Map<?, ?> objMap = null;  

  100.         if (gson != null) {  

  101.             java.lang.reflect.Type type = new com.google.gson.reflect.TypeToken<Map<?, ?>>() {  

  102.             }.getType();  

  103.             objMap = gson.fromJson(jsonStr, type);  

  104.         }  

  105.         return objMap;  

  106.     }  

  107.   

  108.     /** 

  109.      * 将json转换成bean对象 

  110.      *  

  111.      * @param jsonStr 

  112.      * @return 

  113.      */  

  114.     public static Object jsonToBean(String jsonStr, Class<?> cl) {  

  115.         Object obj = null;  

  116.         if (gson != null) {  

  117.             obj = gson.fromJson(jsonStr, cl);  

  118.         }  

  119.         return obj;  

  120.     }  

  121.   

  122.     /** 

  123.      * 将json转换成bean对象 

  124.      *  

  125.      * @param jsonStr 

  126.      * @param cl 

  127.      * @return 

  128.      */  

  129.     @SuppressWarnings("unchecked")  

  130.     public static <T> T jsonToBeanDateSerializer(String jsonStr, Class<T> cl,  

  131.             final String pattern) {  

  132.         Object obj = null;  

  133.         gson = new GsonBuilder()  

  134.                 .registerTypeAdapter(Date.classnew JsonDeserializer<Date>() {  

  135.                     public Date deserialize(JsonElement json, Type typeOfT,  

  136.                             JsonDeserializationContext context)  

  137.                             throws JsonParseException {  

  138.                         SimpleDateFormat format = new SimpleDateFormat(pattern);  

  139.                         String dateStr = json.getAsString();  

  140.                         try {  

  141.                             return format.parse(dateStr);  

  142.                         } catch (ParseException e) {  

  143.                             e.printStackTrace();  

  144.                         }  

  145.                         return null;  

  146.                     }  

  147.                 }).setDateFormat(pattern).create();  

  148.         if (gson != null) {  

  149.             obj = gson.fromJson(jsonStr, cl);  

  150.         }  

  151.         return (T) obj;  

  152.     }  

  153.   

  154.     /** 

  155.      * 根据 

  156.      *  

  157.      * @param jsonStr 

  158.      * @param key 

  159.      * @return 

  160.      */  

  161.     public static Object getJsonValue(String jsonStr, String key) {  

  162.         Object rulsObj = null;  

  163.         Map<?, ?> rulsMap = jsonToMap(jsonStr);  

  164.         if (rulsMap != null && rulsMap.size() > 0) {  

  165.             rulsObj = rulsMap.get(key);  

  166.         }  

  167.         return rulsObj;  

  168.     }  

  169.   

  170. }  

 

引用方式十分简单:

 

Java代码  

  1. (UserInfo)JsonUtil.jsonToBean(jsonString, UserInfo.class);  

 

3、解析复杂Json的方式

Gson支持解析多层结构的Json,当然对于多层解析的效率,暂时还没测试过,估计效率下降不会超过JSONObject...

想解析Json中的Json,Json中的Json数组,Gson提供InstanceCreator结构,来实例化对应的对象,用来加载已解析的json数据。估计解析的流程是,Gson反射属性名称前,先考量能否获得其对应的实例,再对属性对象进行反射、赋值,如此迭代进行...

 

例如,解析Json数组的方式,实现:

 

Java代码  

  1. public class UserInfoResult extends ResponseState implements InstanceCreator<List<UserInfo>>{  

  2.   

  3.     private static final long serialVersionUID = -8701527648781449574L;  

  4.       

  5.     public List<UserInfo> userlist;  

  6.   

  7.     @Override  

  8.     public List<UserInfo> createInstance(Type arg0) {  

  9.         return new ArrayList<UserInfo>(2);  

  10.     }  

  11. }  

 

对比JSONObject,Gson的好处在于:

1、高效,安全的反射,带来高效的解析速度

2、简化的开发流程,对比JSONObject每次都要设计解析的对象,Gson只需要设计值对象,由此带来的就是敏捷的开发

3、良好的支持,Gson属于开源项目,项目位于,现在版本还在不断升级中,建议使用最新的稳定版。