libjson使用详解(linux和windows)-程序员宅基地

我长话短说:

http://download.csdn.net/detail/rongxiaojun/6859823

从官网下的最新的libjson centOS 6.4下使用各种错误,“undifined reference to JSONNode”等。

上面是我经过修改后的库文件,解压后两文件:libjson.a 和 libjson.tar.bz2,把静态库libjson.a放到库文件默认路径/lib/或者/usr/lib/下,然后输入命令:ldconfig

 libjson.tar.bz2解压后是名为libjson的目录,里面是libjson.a需要的头文件,把整个libjson连带目录放到头文件默认路径/usr/local/include/下。


2014.2.14 下午四点半左右出现重大突破:

a.libjson_7.6.1.zip 解压后vim JSONOptions.h,注释掉#define JSON_LIBRARY

b.make后生成libjson.a库文件,将libjson.a加到系统库目录下。

c.回到上级目录,将整个libjson文件夹复制到系统头文件目录下。

unzip libjson_7.6.1
cd libjson
vim JSONOptions.h
注释掉#define JSON_LIBRARY

make
mv libjson.a /usr/local/lib
make clean
cd ..
cp -r libjson /usr/local/include

至此libjson::is_valid及一切应用均步入正轨。


libjson直观图:


对应json字符串:

{
	"childA" : "rong",
	"childB" : 144,
	"childC" :{
		"name" : "bastard",
		"age" :	26,
		"sex" :	"female",
		"schoolID" : 	[
			7728,
			5241
		]
	}
}

{}内一个逗号分隔开的就是一个节点,这个节点的类型由该节点名字及冒号后面的值决定:“”即为字符串节点,整数即为整数节点,{}即为节点节点,[]即为数组节点。


2014.2.15 下午三点:

a.进入libjson目录下,vim JSONOptions.h,注释掉#define JSON_LIBRARY #define JSON_SAFE #define JSON_STREAM #define JSON_VALIDATE,make生成libjson.a,mv libjson.a /usr/local/lib,cd ..,cp -r libjson /usr/local/include/。编译g++ libjson.cpp -o test -ljson,报is_valid不是libjson成员的错误。

b.vim /usr/local/include/libjson/JSONOptions.h,对JSON_SAFE,JSON_STREAM,JSON_VALIDATE取消注释。编译g++ libjson.cpp -o test -ljson,报JSONValidator::isValidRoot(char const*)未定义的错误,这正是对http://download.csdn.net/detail/rongxiaojun/6859823现成库仅修改头文件然后编译libjson.cpp遇到的问题。

至此得出结论:JSONOptions.h中的define决定了哪些文件会被编译进库文件libjson.a,如果一开始没有将validate部分的.cpp文件编译进libjson.a,后期想仅通过修改/usr/local/include/libjson/JSONOptions.h使用validate的功能就会出现函数未定义的错误。




libjsonC++)是以node形式管理数据的:

{
    "RootA" : "Value1",
    "RootB " : "Value2",
    "RootC" : {
        "ChildA" : "String",
        "ChildB" : 42
    }
}

下面的图不好,可以不看。
对应图如下:


JSONkey:value组成,key对应节点名字,value对应节点值。图中方块内是节点名字,椭圆内是节点的值。

根节点有三个孩子,三个孩子名字为:RootARootBRootC,类型分别为JSON_STRINGJSON_STRINGJSON_NODE,三儿子RootC又是节点类型,旗下还有两孙子:ChildAChildB,类型分别为JSON_STRINGJSON_NUMBER,值分别为“String”和42



1.按上图构造JSON结构:

JSONNode n(JSON_NODE);
n.push_back(JSONNode("RootA", "Value1"));
n.push_back(JSONNode("RootB", "Value2"));
JSONNode c(JSON_NODE);
c.set_name("RootC");
c.push_back(JSONNode("ChildA", "String"));
c.push_back(JSONNode("ChildB", 42));
n.push_back(c);



2.访问其中某个节点的值,两种方式[]或者.at(n)

取出二儿子的值:

std::cout<<n[1].as_string()<<std::endl;
std::cout<<n.at(1).as_string()<<std::endl;

取出一个叫“ChildB”的孙子的值:

std::cout<<n[2]["ChildB"].as_int()<<std::endl;
std::cout<<n.at("RootC").at("ChildB").as_int()<<std::endl;

把大儿子的值改为bool型的true:

n["RootA"] = true;
n.at(0) = true;

此时调用

std::cout<<n[0].type()<<std::endl;

输出为3.   正确,因为: 
node的类型分五种:

JSON_NULL          0  //空节点或者说NULL
JSON_STRING        1
JSON_NUMBER        2
JSON_BOOL          3
JSON_ARRAY         4
JSON_NODE          5

调用

std::cout<<n[2].type()<<std::endl;

输出为5.

唯一需要注意的是:取值即取副本


JSONNode x = n[2].as_node();
x[0] = "hello";
std::cout<<x[0].as_string()<<std::endl;
std::cout<<n[2][0].as_string()<<std::endl;

输出:hello     String;      x只是完整的复制了n的小儿子和他的两个孙子节点。


std::cout<<n.size()<<std::endl;

输出为3  返回调用节点的儿子个数,不计孙子。(2014.2.12 15:05追加)返回数组元素个数。



3.字符串解析为JSON

std::string json = "{\"RootA\":\"Value1\",\"RootB\":\"Value2\",\"RootC\":{\"ChildA\":\"String\",\"ChildB\":42}}";
JSONNode n = libjson::parse(json);

自动生成上图中的结构,n即为跟节点。parse会在栈上分配空间,所以不要试图释放n的空间。



4.JSON转化为字符串:

std::string jc = n.write_formatted(); 
std::cout << jc << std::endl;

n为任意节点,write_formatted()会将以n为根节点的JSON结构自动转变为字符串,以上图为例,若n3中构造的节点,输出为:

{
    "RootA" : "Value1",
    "RootB" : "Value2",
    "RootC" : {
        "ChildA" : "String",
        "ChildB" : 42
    }
}

这里可以使用write()替换write_formatted(),使用write()则输出为:

{ "RootA" : "Value1","RootB" : "Value2", "RootC" : {"ChildA" : "String","ChildB" : 42}}


先写这么多,已经足够你操作JSON了,等想到了什么再添加吧。


5.遍历JSON 树:

std::string json = "{\"RootA\":\"Value in parent node\",\"ChildNode\":{\"ChildA\":\"String Value\",\"ChildB\":42}}";
JSONNode n = libjson::parse(json);
ParseJSON(n);

void ParseJSON(const JSONNode & n){
    JSONNode::const_iterator i = n.begin();
    while (i != n.end()){
        // recursively call ourselves to dig deeper into the tree
        if (i -> type() == JSON_ARRAY || i -> type() == JSON_NODE){
            ParseJSON(*i);
        }
 
        // get the node name and value as a string
        std::string node_name = i -> name();
 
        // find out where to store the values
        if (node_name == "RootA"){
            rootA = i -> as_string();
        }
        else if (node_name == "ChildA"){
            childA = i -> as_string();
        }
        else if (node_name == "ChildB")
            childB = i -> as_int();
 
        //increment the iterator
        ++i;
    }
}

6.

std::string json = "{\"RootA\":\"Value in parent node\",\"ChildNode\":{\"ChildA\":\"String Value\",\"ChildB\":42}}";
JSONNode  m = libjson::parse(json);
JSONNode::iterator it = m.find("RootA");
if(it == m.end()) std::cout<<"no the child"<<std::endl;
else std::cout<<it->as_string()<<std::endl;

find函数在以m为根节点的json树上查找名字为“RootA”的儿子节点。

end函数返回m最后一个儿子节点的下一个,标示结束。

m.find("ChildA") 则输出"no the child",因为只找儿子不找孙子。


7.

bool libjson::is_valid(string json)至今不能使用。(于2.14被攻破)


8.

#define JSON_NULL '\0'
#define JSON_STRING '\1'
#define JSON_NUMBER '\2'
#define JSON_BOOL '\3'
#define JSON_ARRAY '\4'
#define JSON_NODE '\5'

这就是std::cout<<n.type()<<std::endl;不能正确输出的原因。type原型:char type(void)。可以使用printf("n.type = %d\n",n.type())或者std::cout<<(int)i->type()<<std::endl2014.2.12 9:15 在此地被伏击。


9.

JSONNode n(JSON_NODE);
n.push_back(JSONNode("RootA", "Hello World"));
JSONNode c(JSON_ARRAY);
c.set_name("ArrayOfNumbers");
c.push_back(JSONNode("", 16));
c.push_back(JSONNode("", 42));
c.push_back(JSONNode("", 128));
n.push_back(c);

printf("the result is : %d %d\n",n[1][0].type(),n[1][0].as_int());

数组即一棵无名孩子树,通过n[i][j]穿层访问适用于子孙及数组。

对应字符串:

{"RootA":"Hello World","ArrayOfNumbers":[16,42,256]}

直观表示:

{
	"RootA" : "Hello World",
	"ArrayOfNumbers" : [
		16,
		42,
		256
	]
}

10.

JSONNode n(JSON_NODE);
n.set_name("2");
std::cout<<n.name()<<std::endl;

设置节点名字,取节点名字。


11.

std::string ss = "{\"ChildNode\":{\"ChildA\":\"String Value\",\"ChildB\":42}}";
JSONNode p = libjson::parse(ss);
std::string child1name = p[0].name();
std::cout<<"child 1 name is "<<child1name<<std::endl;
查看第N个孩子的名字。


12.若节点n是数字类型且123,n.as_string()正常输出123。


13.

JSONNode a(JSON_NODE);
a.push_back(JSONNode("name","idex"));

JSONNode b(JSON_NODE);
b.push_back(a);
b此时的结构为:

{
	"" : {
		"name" : "idex"
	}
}

14.节点名必须是字符串,值可以为数字

n.push_back(JSONNode(14,25.6));是不可以的,14对应的是节点名,只能是字符串。


15.值的类型决定节点的类型:

比如说n.push_back(JSONNode(“14”,25.6));n有个孩子叫"14",这个孩子存的值是浮点数,决定了这个孩子节点是JSON_NUMBER型的。

在此再次强调,type()可以查看节点类型,但是返回值是不可显示字符,分别为'\0','\1', '\2', '\3'等等,需要(int)强制转换再看。

2014.02.25 21:30又着了道了。


16.取浮点数,以15为例

float f = n["14"].as_float();


17.

JSONNode n:
{
	"RootA" : "Hello World",
	"num" : "200800300187",
	"ArrayOfNumbers" : [
		16,
		42,
		128
	],
	"hour:01" : 24.7,
	"hour:03" : 21.4
}
然后:

JSONNode in;
in.set_name("i am tired");

in.push_back(n["RootA"]);
in.push_back(n[1]);

std::string str = in.write_formatted();
std::cout<<str<<std::endl;
输出:

{
	"RootA" : "Hello World",
	"num" : "200800300187"
}

18.libjson下有编码问题:

字符串---->parse---->JSONNode---->write---->正常;

push_back(JSONNode("汉字","汉字"))---->write---->字符串中的汉字变成\u00XX;

push_back(JSONNode("汉字","汉字"))---->n["汉字"].as_string()---->正常;


加入下面两个函数:

void UTF8(std::string& obj){
        int count = 0;
        size_t index = 0;
        while((index = obj.find("\\u00", index)) != std::string::npos){
                count++;
                index++;
        }

        char ch[count+1];
        index = 0;
        std::string substr;
        for(int i = 0; i < count; i++){
                index = obj.find("\\u00", index);
                index += 4;
                substr = obj.substr(index, 2);
                ch[i] = strtol(substr.c_str(), NULL, 16);
        }

        ch[count] = '\0';
        obj = ch;
}

void decode(std::string& obj){
        size_t beg = 0;
        std::string substr;

        while((beg = obj.find("\\u00", 0)) != std::string::npos){
                substr = obj.substr(beg, 18);
                UTF8(substr);
                obj.replace(beg, 18, substr);
        }
}


{"device_name":"测试中文","sex":"男","work":"宇宙总司令","object":"打过银河系,解放全宇宙"}


没有经过decode的str,输出为:

{"device_name":"\u00E6\u00B5\u008B\u00E8\u00AF\u0095\u00E4\u00B8\u00AD\u00E6\u0096\u0087","sex":"\u00E7\u0094\u00B7","work":"\u00E5\u00AE\u0087\u00E5\u00AE\u0099\u00E6\u0080\u00BB\u00E5\u008F\u00B8\u00E4\u00BB\u00A4","object":"\u00E6\u0089\u0093\u00E8\u00BF\u0087\u00E9\u0093\u00B6\u00E6\u00B2\u00B3\u00E7\u00B3\u00BB\u00EF\u00BC\u008C\u00E8\u00A7\u00A3\u00E6\u0094\u00BE\u00E5\u0085\u00A8\u00E5\u00AE\u0087\u00E5\u00AE\u0099"}


libjson在windows下的使用


1.前期准备

a.下载libjson_7.6.1.zip,地址:http://sourceforge.net/projects/libjson/files/?source=navbar

解压得到libjson_7.6.1,进入libjson_7.6.1,里面是名为libjson目录。

b. libjson、libjson/_internal/Source、libjson/_internal/Source/JSONDefs,将三个目录下以”._“开头和以”~“结尾的文件全删了。

c.进入libjson/JSONOptions.h

注释掉#define JSON_LIBRARY;

若VS2010处于Debug模式,则取消#define JSON_DEBUG注释。若VS2010处于Release模式,则无需取消。

至此前期准备完成。


2. 开始配置

a. 将libjson目录添加到项目目录。

b. 将libjson目录添加到工程中:

libjson目录添加JSONOptions.h、libjson.h、_internal目录;

_internal目录下添加Source目录;

Source目录下添加JSONDefs目录和Source下所有文件。

JSONDefs目录下添加JSONDefs所有文件。

c. 项目->属性->配置属性->VC++ 目录->包含目录->添加项目目录中libjson路径,如E:\projects\qt5\qt5\libjson


3.使用

引入头文件后就开始使用

#include "libjson/libjson.h"
#include "libjson/JSONOptions.h"



版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/rongxiaojun/article/details/18414687

智能推荐

 echart横坐标(纵坐标)的值竖着、斜着、省略号(…)显示的实现方法_echarts柱状图显示纵坐标数字-程序员宅基地

目录echart横坐标(纵坐标)的值竖着、斜着、省略号(…)显示的实现方法1、竖着显示2、根据项目多少,判断标注是横着还是竖着3、斜着标注4、只显示4个字,其余的用省略号代替echart横坐标(纵坐标)的值竖着、斜着、省略号(…)显示的实现方法1、竖着显示效果:实现代码: xAxis : [   {     type : 'category',     data : xData,     axisLabel:{..._echarts柱状图显示纵坐标数字

1.9 池化层-深度学习第四课《卷积神经网络》-Stanford吴恩达教授-程序员宅基地

池化层 (Pooling Layers)除了卷积层,卷积网络也经常使用池化层来缩减模型的大小,提高计算速度,同时提高所提取特征的鲁棒性,我们来看一下。先举一个池化层的例子,然后我们再讨论池化层的必要性。假如输入是一个4×4矩阵,用到的池化类型是最大池化(max pooling)。执行最大池化的树池是一个2×2矩阵。执行过程非常简单,把4×4的输入拆分成不同的区域,我把这个区域用不同颜色来标记...

Orcad Capture Cadence 新建原理图多部分smybol和Homogeneous、Heterogeneous类型介绍教程_capture 一个件不同的两个部分 变成了两个件-程序员宅基地

Orcad Capture Cadence 新建原理图多部分smybol和Homogeneous、Heterogeneous类型介绍教程_capture 一个件不同的两个部分 变成了两个件

百度地图4.0多个经纬度展示在地图上_多个经纬度展示轨迹-程序员宅基地

public class YiYuanMapActivity extends BaseActivity{ private ArrayList latitudeList; // 定位相关 LocationClient mLocClient; private MyLocationConfiguration.LocationMode mCurrentMode; p_多个经纬度展示轨迹

Android 组件化 组件上下依赖关系实现_android壳工程依赖组件如何使用-程序员宅基地

1、创建plugin工程2、自定义plugin实现Plugin接口3、在apply(Project)主入口方法内,完成插件的加载1、定义层级关系,从上往下依次为app/component/library/base,2、定位单个组件的类型定义等级,通过等级来控制是否可用做依赖例:将工程区分为api和impl模块,组件之间通信,只能依赖api模块3、自定义插件,如上4、主工程壳里面,实现组件的加载,具体实现代码分为:1、统一配置config.gradle插件部分:1、自定义plugin2、逻辑_android壳工程依赖组件如何使用

【实践】基于强化学习的 Contextual Bandits 算法在推荐场景中的应用-程序员宅基地

文章作者:杨梦月、张露露内容来源:滴滴科技合作出品平台:DataFunTalk导读:本文是对滴滴 AI Labs 和中科院大学联合提出的 WWW 2020 Research Track ..._基于强化学习的实时场景个性化推荐能力

随便推点

C语言小编程之判断一个数是否是2的n次方的巧妙方法_c语言求一个数是2的几次方-程序员宅基地

转自http://blog.csdn.net/qq_26768741/article/details/50917787今天我来分享一个判断一个数是否是2的n次方巧妙方法: 代码如下:#includeint main(){ int num; scanf("%d", νm); while (num) { if (((num) &_c语言求一个数是2的几次方

一个简陋的lua调试器-程序员宅基地

lua没有提供专门的调试器,但却提供了一些接口函数,用以实现你自己的调试器。下面实现了一个简单的基于命令行的lua调试器,提供一些最最基本的调试功能。这里面只用到了3个基本的lua调试函数,debug.sethook,debug.getlocal,debug.getinfo.函数的具体用法和功能可以参照lua手册。下面是简单的实现代码:Command.h#ifnd..._lua调试器

class 原生js获取父元素_如何用原生js通过点击事件获取某一确定的父元素-程序员宅基地

大致看了一下,你的问题是下面这样的吗?............box里面有n个子元素,现在event是绑定在#p上,但是你想找到每次点击的box,就类似于很长的新闻列表,你把event绑定在最外面的container上,但是你想找到每次点击的新闻的单个容器。如果你的问题是上面的,那你可以这样解决var obj = document.getElementById("p");obj.addEventL..._js 点击class,怎么确定是哪一项

Java记录日志_java 记录日志直接存人名-程序员宅基地

Java记录日志基本日志高级日志每个java程序员都很熟悉在有问题的代码中插入一些System.out.println方法来帮助观察程序操作过程。当然一旦发现问题的根源并解决后就删除它…其他地方是如法炮制。所以由于这种需求的存在,Jdk推出了日志API1.很容易的取消全部日志记录2.可以很简单的禁止日志的输出3.日志记录可以被定向到不同的处理器,用于在控制台中显示,或者存储在文件中4.日志记录器和处理器都可以对记录进行过滤。过滤器可以根据实现器制定的标准丢弃掉那些无用的记录项5.日志记录可以采用_java 记录日志直接存人名

谈小米内忧外患的困境-程序员宅基地

小米,用4年时间,从一家名不见经传的小公司,发展成估值100亿美元,包括手机、电视、电视盒子等多条产品线的新型公司。据不同渠道统计,小米手机在国内智能手机市场的占有率,已经迅速追赶华为、中兴这样的传统手机大户,也将多年品牌积累的OPPO、金立等抛在了身后。总结小米的发家史,它本身就是以一个手机行业的"破坏者"的身份出现的,凭借超低价和性价比驰骋沙场,可小米在经历了高速发展之后,出现了无

ffmpeg 编译IOS静态库-程序员宅基地

我使用的配置:xcode4.5,IOS6.0,ipad 1(4.3)一、准备资源1. 到https://github.com/gabriel/ffmpeg-iphone-build下载ffmpeg-iphone-build2.先将gas-preprocessor.pl拷贝到/usr/sbin/目录中。3.到这里下载最新的ffmpeg:http://ffmpeg.org/download.h..._编译ios ffmpeg 静态库