极力推荐一个简单好用的C++JSON库CJsonObject,让使用json如使用C++原生的结构体那般方便,随心所欲。CJsonObject是个优秀的C++JSON库,也许会是你见过的最为简单易用的C++json库。CJsonObject的开源地址是https://github.com/Bwar/CJsonObjecthttps://gitee.com/Bwar/CJsonObject。在开源之初发布的一篇介绍CJsonObject使用的博客《轻量简单好用的C++JSON库CJsonObject》

  CJsonObject开源一年,没有刻意推广,在GitHub上获得130多star和60多fork,事实上当初把CJsonObject开源并建立一个与cJSON的fork关系(事实上CJsonObject与github上的cJSON没有任何关系,CJsonObject使用的cJSON是基于SourceForge上版本比较老的cJSON基础上修改的)是为了多引入一些流量到Bwar倾力打造的另一开源项目Nebula。没想到,倾力打造并且写了好几篇有技术含量的博客文章来推广的Nebula无论star数量还是fork数量都比CJsonObject少(可能跟受众数量有关系)。Bwar始终认为绝大部分使用JSON的场景下,易用性与开发效率才是第一位的,而不是解析性能。在易用性上,说CJsonObject让JSON如C++原生数据结构一般并不为过,所以不避黄婆卖瓜之嫌再极力推荐!CJsonObject有良好的更新和维护,对使用者提的issue响应非常及时,开源一年增加了不少原本不支持但使用者又需要的功能特性。

  CJsonObject在Bwar的重点开源项目Nebula中大量使用,无论对Bwar自己还是对外部开发者,都有持续更新维护的需要。顺便为打个小广告,Nebula是一个强大的IoC网络框架,用于以C++快速构建高并发、分布式和弹性的消息驱动应用程序。适用于即时通讯、数据采集、实时计算、消息推送、web后台服务等应用场景,Nebula已有即时通讯、埋点数据采集及实时分析的生产应用案例。如果觉得CJsonObject不错,给Nebula也点个star,谢谢。

  CJsonObject是基于cJSON全新开发一个C++版的JSON库,CJsonObject的最大优势是轻量,简单好用,开发效率极高。CJsonObject只有4个文件,拷贝到自己代码里源码级集成即可,无须编译成库,且跨平台和编译器。与大部分json解析库访问多层嵌套json非常麻烦不同,CJsonObject对多层嵌套json的读取和生成使用非常简单。

  针对开发者在博客和CJsonObject项目的issue提的问题整理了一个FAQ如下:

FAQ

  • 1. 如何遍历json的key,并取其value?
std::string strTraversingKey;
std::string strTraversingValue;
while(oJson.GetKey(strTraversingKey))
{
if (oJson.Get(strTraversingKey, strTraversingValue))
{
std::cout << strTraversing << " : " << strTraversingValue << std::endl;
}
}

  GetKey()遍历不适用于数组,对json数组调用GetKey()将直接返回false。调用GetKey()函数循环遍历获取当前所在层次的json key,GetKey()返回false表示已取完最后一个key,下次遍历再调用GetKey()将重新从第一个key开始获取。换一种说法,GetKey()遍历json key的返回结果为:true,true,true ... true,false; true,true,true ... true,false; true,true,true ... true,false; 想要遍历多少轮完全由用户自己决定。

  如果需要中断一次遍历并重新开始,可以调用ResetTraversing()函数重置遍历。

std::string strTraversingKey;
std::string strTraversingValue;
while(oJson.GetKey(strTraversingKey))
{
if (strTraversingKey == "Auguest")
{
oJson.ResetTraversing();
break;
}
if (oJson.Get(strTraversingKey, strTraversingValue))
{
std::cout << strTraversing << " : " << strTraversingValue << std::endl;
}
} // 因为上一个遍历中断时调用了ResetTraversing(),所以本次遍历又是从第一个key开始。如果上一个遍历中断时未调用ResetTraversing(),那这次遍历将是从上次终端的位置继续,这通常不是遍历的预期结果,因此,中断遍历时记得ResetTraversing()。
while(oJson.GetKey(strTraversingKey))
{
if (oJson.Get(strTraversingKey, strTraversingValue))
{
std::cout << strTraversing << " : " << strTraversingValue << std::endl;
}
}

  __注意:__对Json当前层次的key进行Add()或Delete()操作,将导致当前遍历失效,下次调用GetKey()将获取key从头开始。

  • 2. Replace一个key时,是否需要原value类型与替换后value类型一致?

  Replace()函数对key进行替换,跟value类型无关。把一个value为int的替换为value为string,或将value替换为object或array都是可以的。但如非必要,建议替换后的value类型跟替换前的value类型相同。

  • 3. []和()的重载有什么区别,为什么要重载这两个操作符?

  []的重载是操作JsonObject或JsonArray的,为了方便一层一层往下取嵌套的json,不适用于string、int等基本json类型;()的重载是Get()系列函数的更便捷的调用,如果十分肯定key是存在的不需要通过Get()的返回值判断是否获取成功,调用()比调用Get()编码要快,不适用于操作JsonObject或JsonArray。

  []和()返回值是不一样的,两者不能混用。

  • 4. 如何用CJsonObject创建类似以下二维数组?
{
"test":[
[{"test":1}],
[{"test":2}]
]
}

  CJsonObject对多层嵌套json的操作非常灵活方便,对嵌套json的生成和读取有许多种灵活用法。

neb::CJsonObject oTest;
oTest.AddEmptySubArray("test");
for (int i = 1; i < 3; ++i)
{
neb::CJsonObject oDimension1;
neb::CJsonObject oDimension2;
oDimension2.Add("test", i);
oDimension1.Add(oDimension2);
oTest["test"].Add(oDimension1);
}
std::cout << oTest.ToString() << std::endl;

  这里给出的只是其中一种写法,其他几种可以参考FAQ#5。

  • 5. 请问一下在使用CJsonObject如何创建如下形式的数组?
{
"employees": [
{ "firstName":"John" , "lastName":"Doe" },
{ "firstName":"Anna" , "lastName":"Smith" },
{ "firstName":"Peter" , "lastName":"Jones" }
]
}

  这里给出三种生成上述json数组的方式:

neb::CJsonObject oJson;
oJson.AddEmptySubArray("employees");
oJson["employees"].Add(neb::CJsonObject("{\"firstName\":\"John\" , \"lastName\":\"Doe\"}"));
oJson["employees"].Add(neb::CJsonObject("{\"firstName\":\"Anna\" , \"lastName\":\"Smith\"}"));
oJson["employees"].Add(neb::CJsonObject("{\"firstName\":\"Peter\" , \"lastName\":\"Jones\"}"));
neb::CJsonObject oJson;
oJson.AddEmptySubArray("employees");
oJson["employees"].Add(neb::CJsonObject("{}"));
oJson["employees"][0].Add("firstName", "John");
oJson["employees"][0].Add("lastName", "Doe");
oJson["employees"].Add(neb::CJsonObject("{}"));
oJson["employees"][1].Add("firstName", "Anna");
oJson["employees"][1].Add("lastName", "Smith");
oJson["employees"].Add(neb::CJsonObject("{}"));
oJson["employees"][2].Add("firstName", "Peter");
oJson["employees"][2].Add("lastName", "Jones");
neb::CJsonObject oJson;
neb::CJsonObject oJohn;
neb::CJsonObject oAnna;
neb::CJsonObject oPeter;
oJohn.Add("firstName", "John");
oJohn.Add("lastName", "Doe");
oAnna.Add("firstName", "Anna");
oAnna.Add("lastName", "Smith");
oPeter.Add("firstName", "Peter");
oPeter.Add("lastName", "Jones");
oJson.AddEmptySubArray("employees");
oJson["employees"].Add(oJohn);
oJson["employees"].Add(oAnna);
oJson["employees"].Add(oPeter);

极力推荐一个简单好用的C++JSON库的更多相关文章

  1. 推荐一个简单、轻量、功能非常强大的C#/ASP.NET定时任务执行管理器组件–FluentScheduler定时器

    在C#WINFORM或者是ASP.NET的WEB应用程序中,根据各种定时任务的需求,比如:每天的数据统计,每小时刷新系统缓存等等,这个时候我们得应用到定时器这个东东. .NET Framework有自 ...

  2. 轻量简单好用的C++JSON库CJsonObject

    1. JSON概述 JSON: JavaScript 对象表示法( JavaScript Object Notation) .是一种轻量级的数据交换格式. 它基于ECMAScript的一个子集.许多编 ...

  3. [转]推荐一个简单、轻量、功能非常强大的C#/ASP.NET定时任务执行管理器组件–FluentScheduler

    在C#WINFORM或者是ASP.NET的WEB应用程序中,根据各种定时任务的需求,比如:每天的数据统计,每小时刷新系统缓存等等,这个时候我们得应用到定时器这个东东. .NET Framework有自 ...

  4. nodejs基础 用http模块 搭建一个简单的web服务器 响应JSON、html

    前端在开发中,大多会想浏览器获取json数据,下面来用nodejs中的http模块搭建一个返回json数据的服务器 var http = require("http"); var ...

  5. 推荐一个 angular 图像加载插件

    推荐一个简单的 Angular 图片加载插件:vgSrc,插件根据图片资源的不同加载状态,显示不同图片,亲测兼容IE-8. 使用 推荐使用 bower 加载: bash bower install v ...

  6. 从一个简单的Delete删数据场景谈TiDB数据库开发规范的重要性

    故事背景 前段时间上线了一个从Oracle迁移到TiDB的项目,某一天应用端反馈有一个诡异的现象,就是有张小表做全表delete的时候执行比较慢,而且有越来越慢的迹象.这个表每次删除的数据不超过20行 ...

  7. 【Java分享客栈】我为什么极力推荐XXL-JOB作为中小厂的分布式任务调度平台

    前言   大家好,我是福隆苑居士,今天给大家聊聊XXL-JOB的使用.   XXL-JOB是本人呆过的三家公司都使用到的分布式任务调度平台,前两家都是服务于传统行业(某大型移动基地和某大型电网),现在 ...

  8. 哪种缓存效果高?开源一个简单的缓存组件j2cache

    背景 现在的web系统已经越来越多的应用缓存技术,而且缓存技术确实是能实足的增强系统性能的.我在项目中也开始接触一些缓存的需求. 开始简单的就用jvm(java托管内存)来做缓存,这样对于单个应用服务 ...

  9. 在Openfire上弄一个简单的推送系统

    推送系统 说是推送系统有点大,其实就是一个消息广播功能吧.作用其实也就是由服务端接收到消息然后推送到订阅的客户端. 思路 对于推送最关键的是服务端向客户端发送数据,客户端向服务端订阅自己想要的消息.这 ...

随机推荐

  1. MethodInterceptor-方法拦截器

    MethodInterceptor 方法拦截器,也就是aop拦截方法 1.使用示例 public interface MethodInterceptor extends Interceptor { O ...

  2. vim配置轻量级IDE

    安装VIM 安装YouCompleteMe的时候, 需要VIM的版本比较高, 一般一些Linux长期支持版的Vim包就比较老, 所以可能需要编译安装. 卸载之前系统中安装的版本: CentOS/Fed ...

  3. CentOS7.3安装JIRA7.10

    准备工作:下载相关安装包,上传到服务器/opt/apps目录下 链接:https://pan.baidu.com/s/15Y5Y3X6AX2ZokWkZKcRrQQ 密码:q0lw 1.安装数据库 y ...

  4. spring boot使用log4j2将日志写入mysql数据库

    log4j2官方例子在spring boot中报错而且还是用的是org.apache.commons.dbcp包 我给改了一下使用org.apache.commons.dbcp2包 1.log4j2. ...

  5. vue.js打包部署线上

    你完成了工程开发,需要部署到外网环境,要进行下面的步骤: 一.首先你要购买一个服务器或者有自己的服务器.我介绍给大家的一个免费的服务器:http://free.3v.do/index.html可以免费 ...

  6. scrapy基础知识之scrapy自动下载图片pipelines

    需要在settings.py配置: ITEM_PIPELINES = { 'scrapy.pipelines.images.ImagesPipeline': 1, }import os IMAGES_ ...

  7. 一、JavaScript概述

    1.Javascript是什么?可以做什么? 1)    JavaScript是一种基于对象和事件驱动的解释性脚本语言, 它具有与Java和C语言类似的语法. 2)    JavaScript可直接嵌 ...

  8. 2050编程赛 冰水挑战 HDU 6495

    题目地址:https://vjudge.net/problem/HDU-6495 思路:我们需要维护的是挑战了n个之后剩余体力值,剩余体力值越大越好dp[N(i)][N(j)],第一个维度,记录当前是 ...

  9. tomcat一键发布

    1. 场景描述 linux下tomcat一键发布,包含停用服务.删除war包.拷贝war包及备份.重启服务等,以前的版本还包含svn更新及打包,后来在生产上怕出问题,改成本地打war包后,ftp上传到 ...

  10. 【bfs】密码锁-C++

    Description 现在一个紧急的任务是打开一个密码锁.密码由四位数字组成,每个数字从 1 到 9 进行编号.每次可以对任何数字加 1 或减 1.当将9加 1 时,数字将变为1,当1减 1 的时, ...