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"



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值