网络通信过程中的数据如何进行结构组织,比较熟悉的有两种方式,JSON和XML,应用都非常广泛,个人项目里使用的是JSON,本文主要是要对JSON的解析做一下总结。
1.关于为何选择JSON
首先JSON和XML都是一种数据交换格式(不应该叫做通信协议)
通信协议:通过通信信道和设备互连起来的多个不同地理位置的数据通信系统,要使其能协同工作实现信息交换和资源共享,它们之间必须具有共同的语言。交流什么、怎样交流及何时交流,都必须遵循某种互相都能接受的规则。这个规则就是通信协议。
-->我们自己在JSON上定义的C/S数据传输体系整体可以看做一个简单的通信协议。
JSON和XML的比较,网络上的信息很多,大致可以参考
http://blog.sina.com.cn/s/blog_6cbdddcb0100m37c.html
实用中的感受就是,XML的可读性相对较好,大量标签使得内容容易被看懂,但这既成就了XML的有点也造就了它的缺点,冗余信息要比JSON大很多,考虑在移动网络环境下,数据传输时间对用户体验的巨大影响,JSON的高效率低冗余就非常有吸引力了。
从json的全称JavaScript Object
Notation就可以猜测它跟JavaScript的“亲戚”关系,其实这个轻量级的数据交换格式是基于JavaScript的一个子集,说白了就是js的对象和数组,所以json对JSP的支持非常好。json采用了独立于语言的文本格式,有两种基本数据结构:对象和数组(两者各种嵌套形成较复杂的json数据)。
Json Array放在中括号[]里面,如[a,c,d...],就跟我们熟悉的数组没本质区别。数组中的元素可以是string, number, false,
true, null, Object对象甚至是array数组。下面是官网给的图解:
Json Object放在大括号{}里面,表示成键值对{key1:value1, key2:value2,
key3:value3,....}。其中(在面向对象的语言里)key为对象的属性,value为对应的属性值。key只能是string类型的,
而value可以是string, number, false, true, null, Object对象甚至是array数组,
也就是说可以存在嵌套的情况。下面是官网给的图解:
解析json数据首先需要知道解析的是json数组还是json对象
2.JSON的封装和解析。
APP(Android)和Server通信通信,这里面,涉及到两端各自的信息封装和解析。总体上,可以找到这三个库可供使用:
net.sf.json
Gson(use on Android)
Org.json(use on Android)
之间的比较总结如下:
net.sf.json:无论是封装还是解析都最方便直接,且支持的解析方式较方便(可映射为Map,List,对象等非常使用的格式),所以在server端使用。但是在我视图将其引入Android上使用时,发现存在不兼容现象。
Android上对于Json的解析有Gson和Org.json两个库可供使用,这个库的实用性接近(但都没有net.sf.json好用)。因为一般发送的数据请求报文都较短,所以在封装上的差异相对不明显。但解析数据时,数据量可能会很大,格式也复杂。对于解析这两个库各有自己的特点,Org.json相对来说更适合去解析层次较多的信息,它能方便的执行一层一层剥开提取的操作;而Gson的面对这种层次较多的数据解析则繁琐的多,但是它有一个特性Org.json没有,Gson库可以直接进行jsonstring和Object以及List<Object>之间的映射,因此,如果json串本身的信息结构就非常简单,且里面的信息本身就是一个一个对象信息,则用Gson做解析代码会意想不到的精简。
这篇博客中有GSON的解析可参考:http://my.eoe.cn/bupt/archive/15365.html?f=nge
下面是我自己项目中的代码:
使用Gson进行封装的代码:
/*Gson封装:工程中使用封装的地方较多,单件模式,简单工厂,最终需要构造的json串如下:
{"data":{"password":"00000","username":"admin"},"head":{"stream_num":0,"message_type":10000,"flag":0,"protocol_version":1}}
*/
public static Gson getGson(){
if(gson==null){
GsonBuilder builder = new GsonBuilder();
builder.excludeFieldsWithoutExposeAnnotation();
gson = builder.create();
}
return gson;
}
/*封装的过程是先将数据存到Map中,然后统一转换*/
public static String encapLoginInfor( String username, String password ) {
Map<String,Integer> headDetail = new HashMap<String,Integer>();
headDetail.put("protocol_version", 1);
headDetail.put("flag", 0);
headDetail.put("message_type", 10000);
headDetail.put("stream_num", 0);
Map<String,String> dataDetail = new HashMap<String,String>();
dataDetail.put("username", username);
dataDetail.put("password", password);
Map<String,Map> finalProtocalMap = new HashMap<String,Map>();
finalProtocalMap.put("head", headDetail);
finalProtocalMap.put("data", dataDetail);
String mapToJson = getGson().toJson(finalProtocalMap);
return mapToJson;
}
使用Gson解析:
public class ParseJSONStringUtil {
/*使用Gson解析*/
public static Gson gson;
public static Gson getGson(){
if(gson==null){
GsonBuilder builder = new GsonBuilder();
builder.excludeFieldsWithoutExposeAnnotation();
gson = builder.create();
}
return gson;
}
/*直接进行串和对象之间的映射,下面的CommonHeader.class即传来的json串对应的类*/
public static CommonHeader parseCommonHeader( String head )
{
CommonHeader commonheader = getGson().fromJson(head, CommonHeader.class);
return commonheader;
}
}
package common;
public class CommonHeader {
private short version;
private short flag;
private short messageType;
private short streamId;
public CommonHeader( short aVersion, short aFlag, short aMessageType, short aStreamId ) {
version = aVersion;
flag = aFlag;
messageType = aMessageType;
streamId = aStreamId;
}
public short getVersion() {
return version;
}
public short getFlag() {
return flag;
}
public short getMessageType() {
return messageType;
}
public short getStreamId() {
return streamId;
}
}
使用Org.json解析:基本思想就是按照Array和Object逐步解析
JSONTokener jsonParser = new JSONTokener(str);
try {
JSONObject infor = (JSONObject)jsonParser.nextValue();
JSONObject headOj= infor.getJSONObject("head");
String messageType = headOj.getString("message_type");
if(messageType.equals("11001")){
JSONObject dataOj = infor.getJSONObject("data");
JSONArray daArray = dataOj.getJSONArray("DAResult");
for(int i=0;i<daArray.length();i++){
JSONObject temp = (JSONObject)daArray.opt(i);
System.out.println((Integer.parseInt(temp.getString("id"))));
}
}
}
(本例中代码解析和封装基本都是针对代码一开头注释中的jsonstring)