原文地址:http://blog.csdn.net/nilreb_nb/article/details/17162709
关于json在vs2012下的配置和json的用法不清楚的自己去google
json的配置可以参考这篇文章:http://blog.csdn.net/joeblackzqq/article/details/9060385
声明:
1、网络数据的传送都是大端模式,而X86操作系统下的vs2012是使用的小端模式,所以需要进行转换
2、我使用的是unicode编码传送的(utf-16be),其实就是一连串16进制数字。
上面概念不清楚的google去。
3、用封装好的json数据转换成unicode编码,进行传送,这样方便客户端和服务器端的数据处理。
假如现在客户端要发送一个包含中文,包含各种中英文的标点符号的json数据("不不!!@#$%^&*.,;'/?。,、;‘")给服务器,要怎么封装?
老规矩,直接上代码(亲测)
(1)json数据的封装
- //send a packet to server
- Value root1;
- //root1["UserName"] = Value("Mike");
- string text1 = "不不!!@#$%^&*.,;'/?。,、;‘";
- root1["UserName"] = Value(text1.c_str());
- //root1["PassWord"] = Value(123);
- //root1["IMEI"] = Value("IMEI_str");
- //root1["OS"] = Value("Windows");
- //root1["MODELS"] = Value("MODELS_str");
- char *LoginReq;//用来存储发送的字节数组,这里只是申明,还没分配内存
- int login_total_length=0;
- TransCoding_UTF8_TO_UNICODE1(root1,LoginReq,login_total_length,0x0010,WaterNum);
- //network judge
- cSocket.Send(LoginReq,login_total_length+1,0);//经过上面的函数,LoginReq数组已经分配了内存并且有了发送的数据
- delete []LoginReq;
这里声明和定义了一个json对象,要发送一个用户名给服务器,主要是利用TransCoding_UTF8_TO_UNICODE1这个函数来进行转码和封装,这里要释放堆内存delete [] ..(因为我在转码函数里面new了一片内存)。下面来看看它:
- //TransCoding From Json To Unicode ( "utf-8" -> "unicode" )
- void TransCoding_UTF8_TO_UNICODE1(const Value &root, char* &LoginReq, int &packet_total_length, int CommandID, int &WaterNum)
- {
- FastWriter fastwriter;
- string LoginReq_body = fastwriter.write(root);//把json对象里面的数据转换成string格式
- wstring login_body = s2ws(LoginReq_body);//s2ws函数是把中英文混杂的string转换成wstring,在下面会给出代码
- char *login_parse = (char *)(&login_body[0]);//因为wstring是宽字节,所以这里给个单字节char指针强制转换一下
- //little endian To big endian(大小端的转换,就是把宽字节里面的两个字节换个位置)
- for(int i=0;i<wcslen(&login_body[0])*2;i+=2)
- {
- int temp;
- temp = login_parse[i];
- login_parse[i] = login_parse[i+1];
- login_parse[i+1] = temp;
- }
- /*for(int i=0;i<wcslen(&login_body[0])*2;i++)
- CCLog("%d-(%d)",i+1,login_parse[i]);*///输出看看转换对不对
- int login_body_length = wcslen(&login_body[0]);//包体的长度(其实就是json对象的长度)
- packet_total_length = login_body_length*2 + 8;//整个数据包的长度(我用的数据包的包头8个字节)
- LoginReq = new char[packet_total_length]; //在堆空间搞一个数组来存储数据包(注意参数的生命周期)
- memcpy(LoginReq+8,login_parse,wcslen(&login_body[0])*2);//把json数据放到第9个位置,包体开始的位置
- //total length(下面的是我的包头信息,8个字节,你可以忽略下面这段代码)
- LoginReq[0] = ((packet_total_length > 0xff)?(packet_total_length/(0xff+1)):(0));
- LoginReq[1] = ((packet_total_length > 0xff)?(packet_total_length%(0xff+1)):(packet_total_length));
- //version number
- LoginReq[2] = 0x00;
- LoginReq[3] = 0x01;
- //command ID
- LoginReq[4] = ((CommandID > 0xff)?(CommandID/(0xff+1)):(0));
- LoginReq[5] = ((CommandID > 0xff)?(CommandID%(0xff+1)):(CommandID));
- //waterNum
- LoginReq[6] = ((WaterNum > 0xff)?(WaterNum/(0xff+1)):(0));
- LoginReq[7] = ((WaterNum > 0xff)?(WaterNum%(0xff+1)):(WaterNum));
- WaterNum++;
- if(WaterNum>9999)
- WaterNum = 1000;
- }
给出s2ws代码
- inline wstring s2ws(const string& s)
- {
- setlocale(LC_ALL, "chs");
- const char* _Source = s.c_str();
- size_t _Dsize = s.size() + 1;
- wchar_t *_Dest = new wchar_t[_Dsize];
- wmemset(_Dest, 0, _Dsize);
- mbstowcs(_Dest,_Source,_Dsize);
- std::wstring result = _Dest;
- delete []_Dest;
- setlocale(LC_ALL, "C");
- return result;
- }
这样就在客户端把一个json对象的数据通过unicode编码发送给了服务器端
(2)json数据的解析
现在服务器传过来一连串的unicode编码的json对象,要怎么解析呢?这个就简单多了,看代码。
- //parse receive_data
- //---------------------------------------------
- string str11 = TransCoding_UNICODE_TO_UTF81(dataBuf,packet_len);//直接用一个string来接收解析完的数据
- Reader reader;
- Value json_object;
- if (!reader.parse(str11.c_str(), json_object)) //然后用json自带的解析器来解析
- CCLog("json parse failed!");
- CCLog("11-%s",json_object["name"].asCString());
- CCLog("11-%d",json_object["age"].asInt());
- //---------------------------------------------
- //TransCoding From Unicode To Json ( "unicode" -> "utf-8" )
- string TransCoding_UNICODE_TO_UTF81(char* dataBuf, const int packet_len)
- {
- //big endian To little endian//同样要进行大小端的转换
- for(int i = 0; i<packet_len-1;i+=2)
- {
- int temp;
- temp = dataBuf[i];
- dataBuf[i] = dataBuf[i+1];
- dataBuf[i+1] = temp;
- }
- wchar_t *parse = (wchar_t *)(dataBuf+8);//一样要进行强制转换一下
- return ws2s(parse);
- }
下面给出ws2s函数代码
- inline string ws2s(const std::wstring& ws)
- {
- std::string curLocale = setlocale(LC_ALL, NULL); // curLocale = "C";
- setlocale(LC_ALL, "chs");
- const wchar_t* _Source = ws.c_str();
- size_t _Dsize = 2 * ws.size() + 1;
- char *_Dest = new char[_Dsize];
- memset(_Dest,0,_Dsize);
- wcstombs(_Dest,_Source,_Dsize);
- std::string result = _Dest;
- delete []_Dest;
- setlocale(LC_ALL, curLocale.c_str());
- return result;
- }
这样客户端就成功接收到了服务器端的json数据。