Json(JavaScript Object Notation)是一种轻量级的数据交换格式,类似XML,但比XML更小更快更容易解析。当前各种流行的web应用框架都对Json提供良好的支持,各种流行开发语言也支持Json解析。
?
Java中解析Json的方式也很多,根据官方的JSONObject库,自己设计的一个抽象工具类:
?
- import ?java.io.Serializable;??
- import ?java.util.List;??
- ??
- import ?org.json.JSONException;??
- import ?org.json.JSONObject;??
- ??
- public ? abstract ? class ?JsonParser?<T? extends ?Serializable>{??
- ??????
- ????abstract ?List<T>?getListFromJson(String?str);??
- ??????
- ????abstract ?T?getObjectFromJson(JSONObject?jobj);??
- ??????
- ????public ?T?getObjectFromJson(String?str)?{??
- ????????try ?{??
- ????????????JSONObject?jsonObject?=?new ?JSONObject(str);??
- ????????????return ?getObjectFromJson(jsonObject);??
- ????????}?catch ?(JSONException?e)?{??
- ????????????e.printStackTrace();???
- ????????}?catch (Exception?e){??
- ????????????e.printStackTrace();??
- ????????}??
- ????????return ? null ;??
- ????}??
- ??????
- ????protected ?String?getValueByName(JSONObject?jobj,?String?name)??
- ????????????throws ?JSONException{??
- ????????if (jobj.has(name)){??
- ????????????return ?jobj.getString(name);??
- ????????}??
- ????????return ? null ;??
- ????}??
- ??????
- }??
?
具体实现的子类如下:
?
- public ? class ?UserInfoParser? extends ?JsonParser<UserInfo>?{??
- ??
- ????private ?UserInfoParser()?{??
- ??????????
- ????}??
- ??????
- ????@Override ??
- ????List<UserInfo>?getListFromJson(String?str)?{??
- ????????try ?{??
- ????????????JSONArray?array?=?new ?JSONArray(str);??
- ????????????int ?len?=?array.length();??
- ????????????ArrayList<UserInfo>?list?=?new ?ArrayList<UserInfo>(len);??
- ????????????for ( int ?i= 0 ;i<len;i++)?{??
- ????????????????UserInfo?info?=?getObjectFromJson(array.getJSONObject(i));??
- ????????????????list.add(info);??
- ????????????}??
- ????????????return ?list;??
- ????????}?catch ?(JSONException?e)?{??
- ????????????e.printStackTrace();??
- ????????}??
- ????????return ? null ;??
- ????}??
- ??
- ????@Override ??
- ????UserInfo?getObjectFromJson(JSONObject?jobj)?{??
- ????????try ?{??
- ????????????UserInfo?info?=?new ?UserInfo();??
- ????????????info.setId(getValueByName(jobj,?UserInfo.NODE_ID));??
- ????????????info.setFace(getValueByName(jobj,UserInfo.NODE_FACE));??
- ????????????info.setUsername(getValueByName(jobj,UserInfo.NODE_USER_NAME));??
- ????????????return ?info;??
- ????????}?catch ?(JSONException?e)?{??
- ????????????e.printStackTrace();??
- ????????}??
- ????????return ? null ;??
- ????}??
- ??
- }??
?
当泛型值对象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能有效分离这些不规范的命名到其他模块代码 中去。
?
?
- public ? class ?UserInfo? implements ?Serializable?{??
- ??
- ????private ? static ? final ? long ?serialVersionUID?=?1050128890144400614L;??
- ??
- ????private ?String?id;??
- ????private ?String?username;??
- ????private ?String?face;??
- ??
- ????public ?String?getId()?{??
- ????????return ?id;??
- ????}??
- ??
- ????public ? void ?setId(String?id)?{??
- ????????this .id?=?id;??
- ????}??
- ??
- ????public ?String?getUsername()?{??
- ????????return ?username;??
- ????}??
- ??
- ????public ? void ?setUsername(String?username)?{??
- ????????this .username?=?username;??
- ????}??
- ??
- ????public ?String?getFace()?{??
- ????????return ?face;??
- ????}??
- ??
- ????public ? void ?setFace(String?face)?{??
- ????????this .face?=?face;??
- ????}??
- ??
- }??
?
?
2、奉上一个基于Gson的Json解析封装工具:
?
- /** ?
- ?*?Gson类库的封装工具类,专门负责解析json数据</br> ?
- ?*?内部实现了Gson对象的单例 ?
- ?*?@author?zhiweiofli ?
- ?*?@version?1.0 ?
- ?*?@since?2012-9-18 ?
- ?*/ ??
- public ? class ?JsonUtil?{??
- ??
- ????private ? static ?Gson?gson?=? null ;??
- ??????
- ????static ?{??
- ????????if ?(gson?==? null )?{??
- ????????????gson?=?new ?Gson();??
- ????????}??
- ????}??
- ??
- ????private ?JsonUtil()?{??
- ??????
- ????}??
- ??
- ????/** ?
- ?????*?将对象转换成json格式 ?
- ?????*? ?
- ?????*?@param?ts ?
- ?????*?@return ?
- ?????*/ ??
- ????public ? static ?String?objectToJson(Object?ts)?{??
- ????????String?jsonStr?=?null ;??
- ????????if ?(gson?!=? null )?{??
- ????????????jsonStr?=?gson.toJson(ts);??
- ????????}??
- ????????return ?jsonStr;??
- ????}??
- ??
- ????/** ?
- ?????*?将对象转换成json格式(并自定义日期格式) ?
- ?????*? ?
- ?????*?@param?ts ?
- ?????*?@return ?
- ?????*/ ??
- ????public ? static ?String?objectToJsonDateSerializer(Object?ts,??
- ????????????final ?String?dateformat)?{??
- ????????String?jsonStr?=?null ;??
- ????????gson?=?new ?GsonBuilder()??
- ????????????????.registerTypeHierarchyAdapter(Date.class ,??
- ????????????????????????new ?JsonSerializer<Date>()?{??
- ????????????????????????????public ?JsonElement?serialize(Date?src,??
- ????????????????????????????????????Type?typeOfSrc,??
- ????????????????????????????????????JsonSerializationContext?context)?{??
- ????????????????????????????????SimpleDateFormat?format?=?new ?SimpleDateFormat(??
- ????????????????????????????????????????dateformat);??
- ????????????????????????????????return ? new ?JsonPrimitive(format.format(src));??
- ????????????????????????????}??
- ????????????????????????}).setDateFormat(dateformat).create();??
- ????????if ?(gson?!=? null )?{??
- ????????????jsonStr?=?gson.toJson(ts);??
- ????????}??
- ????????return ?jsonStr;??
- ????}??
- ??
- ????/** ?
- ?????*?将json格式转换成list对象 ?
- ?????*? ?
- ?????*?@param?jsonStr ?
- ?????*?@return ?
- ?????*/ ??
- ????public ? static ?List<?>?jsonToList(String?jsonStr)?{??
- ????????List<?>?objList?=?null ;??
- ????????if ?(gson?!=? null )?{??
- ????????????java.lang.reflect.Type?type?=?new ?com.google.gson.reflect.TypeToken<List<?>>()?{??
- ????????????}.getType();??
- ????????????objList?=?gson.fromJson(jsonStr,?type);??
- ????????}??
- ????????return ?objList;??
- ????}??
- ??????
- ????/** ?
- ?????*?将json格式转换成list对象,并准确指定类型 ?
- ?????*?@param?jsonStr ?
- ?????*?@param?type ?
- ?????*?@return ?
- ?????*/ ??
- ????public ? static ?List<?>?jsonToList(String?jsonStr,?java.lang.reflect.Type?type)?{??
- ????????List<?>?objList?=?null ;??
- ????????if ?(gson?!=? null )?{??
- ????????????objList?=?gson.fromJson(jsonStr,?type);??
- ????????}??
- ????????return ?objList;??
- ????}??
- ??
- ????/** ?
- ?????*?将json格式转换成map对象 ?
- ?????*? ?
- ?????*?@param?jsonStr ?
- ?????*?@return ?
- ?????*/ ??
- ????public ? static ?Map<?,??>?jsonToMap(String?jsonStr)?{??
- ????????Map<?,??>?objMap?=?null ;??
- ????????if ?(gson?!=? null )?{??
- ????????????java.lang.reflect.Type?type?=?new ?com.google.gson.reflect.TypeToken<Map<?,??>>()?{??
- ????????????}.getType();??
- ????????????objMap?=?gson.fromJson(jsonStr,?type);??
- ????????}??
- ????????return ?objMap;??
- ????}??
- ??
- ????/** ?
- ?????*?将json转换成bean对象 ?
- ?????*? ?
- ?????*?@param?jsonStr ?
- ?????*?@return ?
- ?????*/ ??
- ????public ? static ?Object?jsonToBean(String?jsonStr,?Class<?>?cl)?{??
- ????????Object?obj?=?null ;??
- ????????if ?(gson?!=? null )?{??
- ????????????obj?=?gson.fromJson(jsonStr,?cl);??
- ????????}??
- ????????return ?obj;??
- ????}??
- ??
- ????/** ?
- ?????*?将json转换成bean对象 ?
- ?????*? ?
- ?????*?@param?jsonStr ?
- ?????*?@param?cl ?
- ?????*?@return ?
- ?????*/ ??
- ????@SuppressWarnings ( "unchecked" )??
- ????public ? static ?<T>?T?jsonToBeanDateSerializer(String?jsonStr,?Class<T>?cl,??
- ????????????final ?String?pattern)?{??
- ????????Object?obj?=?null ;??
- ????????gson?=?new ?GsonBuilder()??
- ????????????????.registerTypeAdapter(Date.class ,? new ?JsonDeserializer<Date>()?{??
- ????????????????????public ?Date?deserialize(JsonElement?json,?Type?typeOfT,??
- ????????????????????????????JsonDeserializationContext?context)??
- ????????????????????????????throws ?JsonParseException?{??
- ????????????????????????SimpleDateFormat?format?=?new ?SimpleDateFormat(pattern);??
- ????????????????????????String?dateStr?=?json.getAsString();??
- ????????????????????????try ?{??
- ????????????????????????????return ?format.parse(dateStr);??
- ????????????????????????}?catch ?(ParseException?e)?{??
- ????????????????????????????e.printStackTrace();??
- ????????????????????????}??
- ????????????????????????return ? null ;??
- ????????????????????}??
- ????????????????}).setDateFormat(pattern).create();??
- ????????if ?(gson?!=? null )?{??
- ????????????obj?=?gson.fromJson(jsonStr,?cl);??
- ????????}??
- ????????return ?(T)?obj;??
- ????}??
- ??
- ????/** ?
- ?????*?根据 ?
- ?????*? ?
- ?????*?@param?jsonStr ?
- ?????*?@param?key ?
- ?????*?@return ?
- ?????*/ ??
- ????public ? static ?Object?getJsonValue(String?jsonStr,?String?key)?{??
- ????????Object?rulsObj?=?null ;??
- ????????Map<?,??>?rulsMap?=?jsonToMap(jsonStr);??
- ????????if ?(rulsMap?!=? null ?&&?rulsMap.size()?>? 0 )?{??
- ????????????rulsObj?=?rulsMap.get(key);??
- ????????}??
- ????????return ?rulsObj;??
- ????}??
- ??
- }??
?
引用方式十分简单:
?
- (UserInfo)JsonUtil.jsonToBean(jsonString,?UserInfo. class );??
?
3、解析复杂Json的方式
Gson支持解析多层结构的Json,当然对于多层解析的效率,暂时还没测试过,估计效率下降不会超过JSONObject...
想解析Json中的Json,Json中的Json数组,Gson提供InstanceCreator结构,来实例化对应的对象,用来加载已解析的 json数据。估计解析的流程是,Gson反射属性名称前,先考量能否获得其对应的实例,再对属性对象进行反射、赋值,如此迭代进行...
?
例如,解析Json数组的方式,实现:
?
- public ? class ?UserInfoResult? extends ?ResponseState? implements ?InstanceCreator<List<UserInfo>>{??
- ??
- ????private ? static ? final ? long ?serialVersionUID?=?-8701527648781449574L;??
- ??????
- ????public ?List<UserInfo>?userlist;??
- ??
- ????@Override ??
- ????public ?List<UserInfo>?createInstance(Type?arg0)?{??
- ????????return ? new ?ArrayList<UserInfo>( 2 );??
- ????}??
- }??
?
对比JSONObject,Gson的好处在于:
1、高效,安全的反射,带来高效的解析速度
2、简化的开发流程,对比JSONObject每次都要设计解析的对象,Gson只需要设计值对象,由此带来的就是敏捷的开发
3、良好的支持,Gson属于开源项目,项目位于http://code.google.com/p/google-gson/ ,现在版本还在不断升级中,建议使用最新的稳定版。
?
最后,本文只对比介绍了Gson对Json解析的方面,对于Json的自动化生成,注释的使用,容以后再分享...