TinyJson 是一个基于boost spirit而写的json 文本解析的工具,代码非常精巧,简洁。但是接口用起来却非常繁琐。
举个例子:
string strJson = " { / " login_time/ " : 1246068720 } " ;
2 grammar < char > ::variant var = parse(strJson.begin(), strJson.end());
3 if (var -> type() == typeid(grammar < char > :: object ))
4 {
5 grammar < char > :: object const & obj = boost::any_cast < grammar < char > :: object > ( * var);
6 for (grammar < char > :: object ::const_iterator it = obj.begin(); it != obj.end(); ++ it)
7 {
8 std:: string strName = ( * it).first; // 这里你可以读到名称“login_time”
9
10 if (( * it).second -> type() == typeid( int ))
11 {
12 int nValue = boost::any_cast < int > ( * ( * it).second); // 这里将login_time的值读到一个整型变量里。
13 }
14 }
15 }
我对他进行了一个封装,这样接口用起来就很简单了。代码如下:
template<typename T>
class jobject
{
public:
//construct an object
jobject(){}
jobject(json_string_type const& str){px = parse(str);}
jobject(variant const& val) {px = val;}
//copy construct
jobject(jobject const& obj):px(obj.px){}
//assign value interface
template<class TValue> jobject operator=(TValue val);
//array object interface
jobject_ref operator[](json_string_type const&key);
jobject operator[](int nIndex);
int arrSize(){if(!px) return 0;return (any_cast<array>(*px)).size();}
//map object interface
typedef typename object::iterator iterator;
iterator begin() {if(!px) return iterator();return any_cast<object&>(*px).begin();}
iterator end() {if(!px) return iterator();return any_cast<object&>(*px).end();}
//value get interface
template<class TValue> TValue get() {return any_cast<TValue>(*px);}
//jobject to string
json_string_type to_string();
//null object check
typedef shared_ptr<any> this_type::*unspecified_bool_type;
operator unspecified_bool_type() const
{
return px == 0? 0: &this_type::px;
}
};
这样,用法形式如下:
string strJson = "{ /"server_now/": 12461, /"return_code/": 0, /"params/": {/"rekoo_killer/": /"12//uasdf//uffaa/56/"} }";
jobject<char> obj = parse(strJson.begin(),strJson.end());
string val = obj["params"]["rekoo_killer"].get<string>();
同时,TinyJson 并未附带将JsonObject 转换为string 的代码,这样,我们即使修改了某项值,或者增加减少了object,也无法生成新的string.
试做了一个,代码如下:
template<typename T>
typename jobject<T>::json_string_type jobject<T>::to_string()
{
if(px->empty())
{
return StringHelper<T>::getNull();
}
else if(px->type()==typeid(int))
{
int nValue = any_cast<int>(*px);
return lexical_cast<json_string_type>(nValue);
}
else if(px->type()==typeid(double))
{
double nValue = any_cast<double>(*px);
return lexical_cast<json_string_type>(nValue);
}
else if(px->type()==typeid(std::string))
{
json_string_type strFmt = StringHelper<T>::getStringFmt();;
return str(basic_format<T>(strFmt) % any_cast<json_string_type>(*px));
}
else if(px->type()==typeid(bool))
{
bool nValue = any_cast<bool>(*px);
return nValue?StringHelper<T>::getTrue():StringHelper<T>::getTrue();
}
else if(px->type()==typeid(grammar<T>::object))
{
json_string_type strSubObjs;
object const& obj = any_cast<object>(*px);
json_string_type subObjFmt = StringHelper<T>::getSubObjFmt();// "%s":%s,
for(object::const_reverse_iterator crit = obj.rbegin();crit!=obj.rend();++crit)
{
strSubObjs += str(basic_format<T>(subObjFmt) % crit->first % jobject<T>(crit->second).to_string());
}
if(!strSubObjs.empty())
{
strSubObjs.erase(strSubObjs.size()-1);
}
json_string_type objFmtStr = StringHelper<T>::getObjFmt();
return str(basic_format<T>(objFmtStr)%strSubObjs);
}
else if(px->type()==typeid(grammar<T>::array))
{
json_string_type strSubObjs;
array const& obj = any_cast<array>(*px);
json_string_type subObjFmt = StringHelper<T>::getSubArrFmt();//%s,
for(unsigned int i=0;i<obj.size();++i)
{
strSubObjs += str(basic_format<T>(subObjFmt) % jobject<T>(obj[i]).to_string());
}
if(!strSubObjs.empty())
{
strSubObjs.erase(strSubObjs.size()-1);
}
json_string_type objFmt = StringHelper<T>::getArrFmt();
return str(basic_format<T>(objFmt)%strSubObjs);
}
else
{
*((int*)(0))=5;//force crash to findout problems
return StringHelper<T>::getEmpty();
}
}
全文的代码可以去我发布的下载里下载到。