Json基础及28种c++解析库性能对比

JSON 概念和特点:

    JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation)

    JSON 是轻量级的文本数据交换格式,类似 XML,但比 XML 更小、更快,更易解析

    JSON 独立于语言 *

    JSON 具有自我描述性,更易理解  。

 

JSON的创建方式与创建 JavaScript 对象的代码相同。

Json的格式:

{

    "project_type": "javascript",

    "debugMode" : 1,

    "showFPS" : true,

    "frameRate" : 60,

    "id" : "gameCanvas",

    "renderMode" : 0,

    "engineDir":"frameworks/cocos2d-html5",

    "modules" : ["cocos2d", "extensions"],

    "jsList" : [

        "src/loader/loaderRes.js",

        "src/loader/loaderScene.js"

    ]

}

 

JSON 值可以是:

       数字(整数或浮点数)

       字符串(在双引号中)

       逻辑值(true 或 false)

       数组(在方括号中)

       对象(在花括号中)

       null。

JSON 是 JavaScript 原生格式。JavaScript可以直接使用JSON,不需要调用api或工具包。

由于JSON的易用性,其他语言也提供了强大的JSON 解析器和 JSON 库。c++语音有28种json库。下面的图表是对28种json库的评估:

符合标准程度(越高越好):

解析至DOM的时间(越低越好):

把DOM生成含换行及缩进的JSON的时间(越低越好):

可执行文件(把JSON解析至DOM,然后统计JSON类型)的大小(越低越好):


1:使用Rapidjson解析字符串成json格式数据

1、创建一个rapidjson::Document对象rapidJson的相关操作都在Document类中

   rapidjson::Document

2、调用Parse方法解析json数据

   doc.Parse<0>(data.c_str());

3、使用HasParseError()判断解析出来的document是否正确。解析正确才能做进一步操作。

2:使用Rapidjson读取和更改数据

在rapidJson中,使用rapidjson::Value代表json数据中的值。rapidjson::Value其实就是js中的var,可以把rapidjson::Value当作int,也可以当作string,也可以当作数组等。对于定义rapidjson::Value value,只是一个定义,还没有决定其数据类型,如果明确value的类型,再转成相应的格式。Value的类型包括int,Double,string,bool,array,obejct,null。

json使用key-value的方式,读取数据时使用脚标的方式:rapidjson::Value  &value=doc["hello"];

在获取脚本之前,还可以使用HasMember方法判断是否有这个键值对

然后判断value的类型:value.IsString()判断是否是字符串,IsArray()判断是否是数组等

判断好数据的类型后,可以调用对应的方法获取c/c++数据类型。比如如果value是字符串,则可以通过getString方法获取字符串的值。

并且可以通过SetString方法修改该value的值。

除了修改value的值,也可以修改value的类型,通过set+类型的方法设置,有下面这些方法可以设置value的值。

vall.SetArray()

vall.SetArrayRaw()

vall.SetBool()

vall.SetDouble()

vall.SetInt()

vall.SetNull()

vall.SetObject()

vall.SetString()

vall.SetStringRaw()

vall.SetUint();

vall.SetUint64()

3:把json数据转成字符串

使用rapidjson::Writer 把 rapidjson::Value 转成符合json数据格式的字符串:

先声明一个rapidjson::StringBuffer类型的数据

    rapidjson::StringBuffer  buffer;

再创建一个rapidjson::Writer对象

    rapidjson::Writer<rapidjson::StringBuffer>  writer(buffer);

    doc.Accept(writer); 

然后就可以通过buffer.GetString()获取c/c++的字符串了。

4:使用Rapidjson添加、删除数据

Rapidjson除了能够读取和修改数据,还能添加和删除数据。

添加数据时,先获取一个分配器

  rapidjson::Document::AllocatorType  &allocator = doc.GetAllocator();

添加一个数:

doc.AddMember("age",15,allocator);

添加一个字符串:

doc.AddMember("name","liao li",allocator);

///添加一个null对象

rapidjson::Value nullObject(rapidjson::kNullType);

doc.AddMember("null",nullObject,allocator);///<往分配器中添加一个对象

添加一个对象:

rapidjson::Value  object(rapidjson::kObjectType);///<创建数组里面对象。

object.AddMember("age",40,allocator);

object.AddMember("name","father ",allocator);

doc.AddMember("father",object,allocator);

///添加一个数组对象

rapidjson::Value  array(rapidjson::kArrayType);///<创建一个数组对象

array.PushBack(1,allocator);

array.PushBack(2,allocator);

array.PushBack(3,allocator);

doc.AddMember("array",array,allocator)

///在已有的数组中添加一个成员对象

rapidjson::Value  &aArray1=doc["array"];

aArray1.PushBack(4,allocator);


代码实操:

直接修改前面http的代码

#include "TestRapidJson.h"
#include "cocos2d\external\json\rapidjson.h"
#include "cocos2d\external\json\document.h"
#include "cocos2d\external\json\stringbuffer.h"
#include "cocos2d\external\json\writer.h" Scene* TestRapidJson::createScene()
{
auto scene = Scene::create();
auto layer = TestRapidJson::create();
scene->addChild(layer);
return scene;
} bool TestRapidJson::init()
{
if ( !Layer::init() )
{
return false;
} //post
auto postReq = new HttpRequest();
postReq->setTag("type post");
postReq->setUrl("http://httpbin.org/post");
postReq->setRequestType(HttpRequest::Type::POST);
std::vector<std::string> header;
header.push_back("Content-Type:application/json;charset=utf-8");
postReq->setHeaders(header);
const char* reqData = "response Data";
postReq->setRequestData(reqData,strlen(reqData));
postReq->setResponseCallback(CC_CALLBACK_2(TestRapidJson::complete,this)); auto client2 = HttpClient::getInstance();
client2->send(postReq);
postReq->release(); return true;
}
void TestRapidJson::complete(HttpClient *client,HttpResponse *response)
{
log("request tag is:%s",response->getHttpRequest()->getTag());
log("response code is:%d",response->getResponseCode());
if(response->isSucceed())
{
/*std::vector<char> * data = response->getResponseData();
log("response data is:");
for (int i = 0; i < data->size(); i++)
{
log("%c",(*data)[i]);
}*/
std::vector<char> * data = response->getResponseData();
std::stringstream oss;
for (int i = 0; i < data->size(); i++)
{
oss<<(*data)[i];
}
std::string str = oss.str();
log("response data is:%s",str.c_str()); // 1:创建一个rapidjson::Document对象
rapidjson::Document doc;
// 1:调用Parse方法解析json数据
doc.Parse<0>(str.c_str());
// 1:判断解析是否成功
if (doc.HasParseError())
{
log("json parse error : %s",doc.GetParseError());
}else//解析成功之后的操作
{
log("parse success");
// 2:判断类型,判断是否有该数据
if (doc.IsObject()&&doc.HasMember("data"))
{
// 2:读取值
rapidjson::Value &value = doc["data"];
if (value.IsString())
{
// 2:获取值
log("data is :%s",value.GetString());
}
} if (doc.IsObject()&&doc.HasMember("json"))
{
// 2:设置值
doc["json"].SetInt(15);
log("json is :% d",doc["json"].GetInt() );
} // 3:声明一个rapidjson::StringBuffer类型的数据
rapidjson::StringBuffer buffer;
// 3:创建一个rapidjson::Writer对象
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
doc.Accept(writer);
// 3:获取c/c++的字符串
log("json string is: %s",buffer.GetString()); // 4:获取一个分配器
rapidjson::Document::AllocatorType &allocator=doc.GetAllocator();
//添加整数
doc.AddMember("int",20,allocator); //添加字符串
doc.AddMember("string","string value",allocator);
//添加一个null对象
rapidjson::Value nullObj(rapidjson::kNullType);
doc.AddMember("null",nullObj,allocator);
//添加了一个对象
rapidjson::Value obj(rapidjson::kObjectType);
obj.AddMember("name","xiaoli",allocator);
obj.AddMember("age",20,allocator);
obj.AddMember("height",180,allocator); doc.AddMember("personInfo",obj,allocator); //添加一个数组
rapidjson::Value arr(rapidjson::kArrayType); arr.PushBack(1,allocator);
arr.PushBack("string in array",allocator); rapidjson::Value obj1(rapidjson::kObjectType);
obj1.AddMember("name","xiaoli",allocator);
obj1.AddMember("age",20,allocator);
obj1.AddMember("height",180,allocator); arr.PushBack(obj1,allocator); doc.AddMember("arr",arr,allocator); rapidjson::StringBuffer buffer1;
rapidjson::Writer<rapidjson::StringBuffer> writer1(buffer1);
doc.Accept(writer1);
log("modified data is: %s",buffer1.GetString()); }
}else
{
log("error msg is:%s",response->getErrorBuffer());
}
}

Cocos2d-X网络编程(5) 使用Rapidjson解析数据的更多相关文章

  1. Python之路(第三十三篇) 网络编程:socketserver深度解析

    一.socketserver 模块介绍 socketserver是标准库中的一个高级模块,用于网络客户端与服务器的实现.(version = "0.4") 在python2中写作S ...

  2. 网络编程 --- URLConnection --- 读取服务器的数据 --- java

    使用URLConnection类获取服务器的数据 抽象类URLConnection表示一个指向指定URL资源的活动连接,它是java协议处理器机制的一部分. URL对象的openConnection( ...

  3. TCP/IP网络编程之地址族与数据序列

    分配IP地址和端口号 IP是Internet Protocol(网络协议)的简写,是为收发网络数据而分配给计算机的值.端口号并非赋予计算机的值,而是为区分程序中创建的套接字而分配给套接字的序号 网络地 ...

  4. C/C++网络编程3——地址族与数据序列

    C/C++网络编程2中介绍了套接字,这一节介绍给套接字分配ip和端口号.ip用于标识一台主机,端口号用于标识一个主机中的一个应用程序,端口号占16位,0到65535,其中0到1023是知名端口号. 表 ...

  5. 网络编程--使用UDP发送接收数据

    package com.zhangxueliang.udp; import java.io.IOException; import java.net.DatagramPacket; import ja ...

  6. Android网络编程Socket【实例解析】

    Socket 事实上和JavaWeb 里面的Socket一模一样 建立客服端,server端,server开一个port供客服端訪问 第一步创建server端:(这里把为了便于解说.把server端, ...

  7. Linux网络编程六、报文解析(1)

    一.pcap文件解析 依赖的库:libpcap,头文件:pcap/pcap.h 获取pcap文件:tcpdump,-i:指定监听接口,默认配置好的最小的号码的接口.-w:指定存入文件,将原始报文存入指 ...

  8. JAVA的网络编程

    网络编程 网络编程对于很多的初学者来说,都是很向往的一种编程技能,但是很多的初学者却因为很长一段时间无法进入网络编程的大门而放弃了对于该部分技术的学习. 在 学习网络编程以前,很多初学者可能觉得网络编 ...

  9. JAVA网络编程【转】出处不详

    网络编程 网络编程对于很多的初学者来说,都是很向往的一种编程技能,但是很多的初学者却因为很长一段时间无法进入网络编程的大门而放弃了对于该部分技术的学习. 在 学习网络编程以前,很多初学者可能觉得网络编 ...

随机推荐

  1. UVA - 10829 L-Gap Substrings (后缀自动机+线段树启发式合并)

    题意:统计一段字符串中形如UVU的子串个数(其中V的长度固定为g). 问题等价于求满足$g+1\leqslant |j-i|\leqslant g+LCP(i,j)$的后缀(i,j)的对数,即$\su ...

  2. P1801 黑匣子[对顶堆]

    没错我就是专门找对顶堆练习题的.现在感觉对顶堆使用面有点狭窄.这道题由于我询问是随时间单调增的,而且数据比较友好,应该是插入几次就询问一下的.而中位数那题也是经常询问的.如果查询的东西不单调,或者查询 ...

  3. Web前端经典面试试题(一)

    本篇收录了一些面试中经常会遇到的经典面试题,并且都给出了我在网上收集的答案.眼看新的一年马上就要开始了,相信很多的前端开发者会有一些跳槽的悸动,通过对本篇知识的整理以及经验的总结,希望能帮到更多的前端 ...

  4. windows笔记本命令行方式建立wifi热点

    建立热点: @echo off netsh wlan set hostednetwork mode=allow netsh wlan set hostednetwork ssid=热点名 key=密码 ...

  5. JAVA笔记8-对象转型casting

    1.规则 (1)基类(父类)的引用类型变量可以指向其子类对象:(向上转型) (2)基类的引用不可以访问其子类对象新增加的成员(属性和方法): (3)可以使用“引用变量 instanceof 类名”来判 ...

  6. css-动画,a标签下,文字加下划线,而且动画是由中间向两边扩展开

    效果: html: <div class="warp"> <a class="welcome">期待您的参与</a> < ...

  7. 线上 CPU100% 排查方案

    问题:生产服务器上部署了几个java程序,突然出现了CPU100%的异常告警,你如何定位出问题呢? 下面给出两种系统下的排查步骤,都是一模一样的,只是命令稍有区别! 查消耗cpu最高的进程PID 根据 ...

  8. ES6 Promise使用介绍

    1.什么是Promise Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大. 这么说可能不够直观的理解,看下面的两个例子 // callback回调函数 ...

  9. python动态的添加方法

    1.动态的创建实例方法 1 class Person(object): 2 def __init__(self,name,age): 3 self.name = name 4 self.age =ag ...

  10. QtQtConcurrent 使用方式

    说明:QtConcurrent 的线程函数启动方式略述. 1) 全局函数或静态函 ,作为线程函数 void threadFunc() { //...add } QtConcurrent::run(th ...