一个c++版本的json实现思路

来源:互联网 发布:什么软件外卖货到付款 编辑:程序博客网 时间:2024/06/04 18:48

JSON的c/c++实现版本很多,可是用起来总是感觉不是那么顺手,于是就把自己能用的所谓奇技淫巧全都使了出来,可是貌似还是不尽满意。不过还是贴出来,算是当个纪念吧。

#include <unordered_map>#include <algorithm>#include <sstream>#include <vector>#include <map>typedef std::unordered_map<std::string,std::string> object_container;

namespace value_object_detail{static const std::string string_type = "string";static const std::string number_type = "number";static const std::string bool_type = "bool";static const std::string object_type = "object";static const std::string array_type = "array";static const std::string null_type = "null";

JSON数值实现类,用来尽可能的使得字符串数值和c/c++原生数据类型无缝集成

class json_value{public:json_value(object_container& inst,const std::string& key):inst_(inst),preffix_(key){}json_value(const json_value& jv):inst_(jv.inst_),preffix_(jv.preffix_){}protected:void set_meta_information(const std::string& key,int index = 0){std::string& key_type = inst_[preffix_];const char* assert_type = NULL;std::stringstream ss;if(!key.empty()){ss << "object@" << key << ",";assert_type = "array@";}else{ss << "array@" << index << ",";assert_type = "object@";}std::string append_type =  ss.str();if(std::string::npos != key_type.find(assert_type)){del();inst_[preffix_] = append_type;return;}//assign repeatif(std::string::npos == key_type.find(append_type)){key_type += append_type;}}public:json_value operator[](int i){using namespace value_object_detail;set_meta_information("",i);std::stringstream ss;ss << preffix_ << "." << i;return json_value(inst_,ss.str());}json_value operator[](const std::string& key){using namespace value_object_detail;set_meta_information(key);return json_value(inst_,key.empty() ? preffix_ : preffix_ + "." + key);}public:std::string& operator*(){return inst_[preffix_];}bool operator!()const{return inst_.end() == inst_.find(preffix_);}public:const std::string& str_value()const {const static std::string ret;object_container::const_iterator it = inst_.find(preffix_);return inst_.end() == it ? ret : it->second;}const std::string& str_key()const {return preffix_;}public:const std::string& type_string()const{const std::string& val = str_value();if(val.empty()){return null_type;}if(std::string::npos != val.find("array@")){return array_type;}if(std::string::npos != val.find("object@")){return object_type;}return number_type;}public:template<class Fn>void for_each(Fn f){object_container::const_iterator it = inst_.find(preffix_);const std::string& type = type_string();if(inst_.end() == it || (array_type != type && object_type != type)){return ;}std::string sub_key = "";std::string::size_type posb = 0,pose = 0,posn = std::string::npos;object_container::const_iterator sub_it;for(posb = pose = 0;;posb += 1,pose += 1){posb = it->second.find('@',posb);pose = it->second.find(',',pose);if(posn == posb || posn == pose){break;}sub_key = it->second.substr(posb+1,pose - posb -1);sub_it = inst_.find(preffix_ + "." + sub_key);if(inst_.end() != sub_it){f(sub_key,sub_it->second);}else{f(sub_key,"");}}}void del(){const std::string& type = type_string();if(array_type == type){int i = 0;for(json_value jv = this->operator[](i);!!jv;++i){jv.del();}}else if(object_type == type){for_each([this](const std::string& key,const std::string& v){json_value sub_item = this->operator[](key);sub_item.del();});}inst_.erase(preffix_);}public:template<class T>json_value& operator=(const T& val){*this << val;return *this;}json_value& operator=(const std::string& val){inst_[preffix_] = val;return *this;}json_value& operator=(const json_value& jv){inst_ = jv.inst_;preffix_ = jv.preffix_;return *this;}private:object_container& inst_;std::string preffix_;};

各种赋值包装

template<class T>json_value& operator <<(json_value& jv,const T& val){std::stringstream ss;ss << val;*jv = ss.str();return jv;}template<class T>json_value& operator <<(json_value& jv,const bool& val){*jv = val ? "true" : "false";return jv;}template <class T> json_value& operator<<(json_value& jv,const std::vector<T>& val){int i = 0;std::for_each(val.begin(),val.end(),[&i,&jv](const T& v){jv[i++] = v;});return jv;}template <class T, int N> json_value& operator<<(json_value& jv,const T (&val)[N]){int i = 0;std::for_each(&val[0],&val[N],[&i,&jv](const T& v){jv[i++] = v;});return jv;}template<class T>json_value& operator>>(json_value& jv,T& val){std::stringstream ss;ss << *jv;ss >> val;return jv;}template<>json_value& operator>>(json_value& jv,bool& val){val = ("true" == *jv);return jv;}template<>json_value&  operator>>(json_value& jv,std::string& val){val = *jv;return jv;}template <class T> json_value&  operator>>(json_value& jv,std::vector<T>& val){int i = 0;jv.for_each([&val,&jv,&i](const std::string& k,const std::string&v){T t;jv[i++] >> t;val.push_back(t);});return jv;}template <class T, int N> json_value& operator>>(json_value& jv,T (&val)[N]){int i = 0;jv.for_each([&val,&jv,&i](const std::string& k,const std::string&v){jv[i] >> val[i];++i;});return jv;}

一个简单的JSON解析器,没有语法检测,而且效率还不敢恭维,实在有重构的必要

class json_parser{public:json_parser(json_value& value):values_(value){}protected:json_value values_;std::list<std::string> items_;public:bool operator()(const std::string& json_str){state_ op(items_);std::for_each(json_str.begin(),json_str.end(),op);parse_items();return items_.empty();}bool operator()(std::istream& is){state_ op(items_);std::for_each(std::istream_iterator<char>(is),std::istream_iterator<char>(),op);parse_items();return items_.empty();}protected:void parse_items(){if("{" != items_.front() && "[" != items_.front()){items_.push_front("{");items_.push_back("}");}parse_object(values_);}protected:class state_{private:bool in_close_;std::string item_;std::list<std::string>& items_;protected:bool in_string(const char& c){if(!in_close_){return false;}if('"' == c && '\\' != item_.back()){in_close_ = false;return false;}if(item_.empty() || '\\' != item_.back()){item_.push_back(c);return true;}switch(c){case '"': item_.back() = '"'; break;case 't': item_.back() = '\t'; break;case 'n': item_.back() = '\n'; break;case 'r': item_.back() = '\r'; break;case '\\': item_.back() = '\\'; break;default: item_.push_back(c);break;}return true;}public:state_(std::list<std::string>& items):in_close_(false),items_(items){}public:void operator()(const char& c){if(in_string(c)){return;}switch (c){case '"': {if(!in_close_ && !item_.empty()){items_.push_back(item_);item_.clear();break;}in_close_ = item_.empty();break;  }case '{':case '}':case '[':case ']':{item_.push_back(c);items_.push_back(item_);item_.clear();break;}case ':':case ',':{item_.empty() ? (void) 0 : items_.push_back(item_);item_.clear();break;}case ' ':case '\t':case '\n':case '\r':{break;}default:{item_.push_back(c);break;}}}};protected:void parse_object(json_value& jv){if("{" != items_.front()){return;}for(items_.pop_front();"}" != items_.front();){parse_item(jv);}items_.pop_front();}void set_item_value(json_value& jv){std::string  val = items_.front();if(val == "["){parse_array(jv);return;}if(val == "{"){parse_object(jv);return;}*jv = val;items_.pop_front();}void parse_array(json_value& jv){if("[" != items_.front()){return;}int i = 0;for(items_.pop_front();"]" != items_.front(); ++i){set_item_value(jv[i]);}items_.pop_front();}void parse_item(json_value& jv){std::string  key = items_.front();items_.pop_front();set_item_value(jv[key]);}};

一个JSON字符串生成器,同样不是很严格

class json_maker {public:json_maker(std::ostream& os,json_value& jv):os_(os),json_vlaue_(jv){}protected:std::ostream& os_;json_value& json_vlaue_;public:void operator()(){os_ << "{";json_vlaue_.for_each([this](const std::string& k,const std::string& v){this->to_string(this->json_vlaue_[k]);this->os_ << ",";});#define set_last_op(c) do{\std::ostream::off_type pos = os_.tellp();\os_.seekp(pos -1);\os_.write(c,1);\}while(0)set_last_op("}");}protected:void to_string(json_value& item,bool array_item = false){const std::string& type = item.type_string();if(!array_item){const std::string& preffix_ = item.str_key();std::string::size_type pos = preffix_.find_last_of('.');std::string key = (std::string::npos == pos) ? preffix_ : preffix_.substr(pos + 1);os_ << "\"" << key << "\":";}if(array_type == type){os_ << "[";int i = 0;for(json_value jv = item[i];!!jv; jv = item[++i]){to_string(jv,true);os_ << ",";}set_last_op("]");}else if(object_type == type){os_ << "{";item.for_each([this,&item](const std::string& k,const std::string& v){to_string(item[k]);this->os_ << ",";});set_last_op("}");}else{formart_value(item.str_value());}}#undef set_last_opprotected:bool isnumber(const std::string& str)const{for(const char* cstr = str.c_str();*cstr;++cstr){switch (*cstr){case '+':case '-':case '.':case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':case 'e':case 'E':{break;}default:return false;break;}}return true;}protected:void formart_value(const std::string& val){if(val.empty()){os_ << "\"\"";return;}if("true" == val || "false" == val || isnumber(val)){os_ << val;return ;}os_ << "\"";std::for_each(val.begin(),val.end(),[this](const char& c){switch (c){case '"':  this->os_ << "\\\""; break;case '\t': this->os_ << "\\t";  break;case '\n': this->os_ << "\\n";  break;case '\r': this->os_ << "\\r";  break;case '\\': this->os_ << "\\\\"; break;default:{this->os_ << c;break;}}});os_ << "\"";}};}//end namespace

下面是正JSON使用类的一个包装

class value_object {protected:object_container values_;public:value_object(){}value_object(const std::string& json_str){parse_string(json_str);}private:typedef value_object_detail::json_value json_value;public:template<class T>value_object& operator()(const std::string& key,const T& value){using namespace value_object_detail;json_value(values_,"root." + key) << value;return *this;}template<class T>value_object& operator()(const std::string& key,T& value,bool& exist){using namespace value_object_detail;json_value jv(values_,"root." + key);exist = !!jv;if(exist) jv >> value ;return *this;}public:json_value operator[](const std::string& key){return json_value(values_,"root")[key];}json_value operator[](int i){return json_value(values_,"root")[i];}public:bool operator==(const value_object& vo)const{if(this == &vo){return true;}if(vo.values_.size() != values_.size()){return false;}bool result = true;std::for_each(vo.values_.begin(),vo.values_.end(),[this,&result](const object_container::const_reference cr){if(!result){return;}if(std::string::npos != cr.second.find("object@")){return;}if(std::string::npos != cr.second.find("array@")){return;}object_container::const_iterator it = this->values_.find(cr.first);result = (it != this->values_.end()) && (it->second == cr.second);});return result;}public:std::ostream& to_string(std::ostream& os){using namespace value_object_detail;json_maker(os,json_value(values_,"root"))();return os;}void parse_string(const std::string& json_str){using namespace value_object_detail;json_parser jp(json_value(values_,"root"));jp(json_str);}};

测试程序

#include <iostream>#include <string>#include <vector>struct test_json_obj{int ta;double tb;std::string ts;public:bool operator==(const test_json_obj& r)const{return ta == r.ta && int(tb * 1000) == int(r.tb * 1000) && ts == r.ts; }};std::ostream& operator<<(std::ostream& os,const test_json_obj& jo){os << "{\nta:" << jo.ta << ",\ntb:" << jo.tb << ",\nts:\"" << jo.ts << "\"\n}\n";return os;}namespace value_object_detail{json_value& operator<<(json_value& vc,const test_json_obj& val){vc["ta"] = val.ta;vc["tb"] = val.tb;vc["ts"] = val.ts;return vc;}json_value& operator>>(json_value& vc, test_json_obj& tj){vc["ta"] >> tj.ta;vc["tb"] >> tj.tb;vc["ts"] >> tj.ts;return vc;}}int main(int argn,char* argv[]){value_object vo;bool exist,null_value;{test_json_obj obj = {1,6.248f,"haha, object"},obj1 = {0,0.0f,""},obj2;test_json_obj obj_array1[] = {obj,obj1},obj_array2[3];std::vector<test_json_obj> v1,v2;v1.push_back(obj);v1.push_back(obj1);vo["aa"] = 1;vo("v1",obj)("array" ,obj_array1)("vector" ,v1);vo("v1",obj1,exist)("array",obj_array2,exist)("vector" ,v2,exist)("v2",obj2,null_value);assert( exist || !null_value);assert(obj1 == obj);assert(v2 == v1);for(int i = 0; i < 2; ++i){assert(obj_array1[i] == obj_array2[i]);}vo["v1"] = v1;v2.clear();vo["v1"] >> v2;assert(v1 == v2);std::for_each(v2.begin(),v2.end(),[](const test_json_obj& v){std::cout << v << ",";});vo["obj_array"] = obj_array1;vo["obj_array"] >> obj_array2;for(int i = 0; i < 2; ++i){assert(obj_array1[i] == obj_array2[i]);}int int_array1[] = { 1,2,3,4,5,6,7},int_array2[10] = {0};vo["int_array"] = int_array1;vo["int_array"] >> int_array2;for(int i = 0; i < 7; ++i){assert(int_array1[i] == int_array2[i]);}vo["int"] = 0;vo["double"] = 3.1425f;vo["string"] = std::string("hi test");int a;double b; std::string s;vo("int",a,exist)("double",b,exist)("string",s,exist);assert(a == 0 && int(31425) == int(b * 10000) && s == "hi test");vo["obj1"] = obj;vo["obj1"] >> obj1;assert(obj == obj1);std::cout << "old_obj = " << obj1 << std::endl;vo["obj1.ta"] = 2;vo["obj1.tb"] = 3.1415f;vo["obj1.ts"] = std::string("hi test");vo["obj1"] >> obj;assert(obj.ta == 2 && int(obj.tb * 1000) == int(3141) && obj.ts == "hi test");std::cout << "new_obj = " << obj;}{const char* json_str = "{"\"a:1,"\"\"b \" :2,"\"c : \"asdf\\\"asdf\","\"ab : [1,2,3,4,\"asdfasdf\"],"\"ao : [{"\"a:1,"\"b:2,"\"c:\"asdf\""\"}]"\"}";vo.parse_string(json_str);int a, b;std::string c;vo("a",a,exist)("b ",b,exist)("c",c,exist);assert(a == 1 && b == 2 && c == "asdf\"asdf");vo["ab"][0] >> b;vo["ab"][1] >> a;vo["ab"][4] >> c;assert(a == 2 && b == 1 && c == "asdfasdf");vo["ao"][0]["a"] >> a;vo["ao"][0]["b"] >> b;vo["ao"][0]["c"] >> c;assert(a == 1 && b == 2 && c == "asdf");std::stringstream ss;vo.to_string(ss) << std::endl;std::cout << ss.str() << std::endl;}{const char* json_str = "{"\"a:1,"\"\"b \" :2,"\"c : \"asdf\\\"asdf\","\"ab : [1,2,3,4,\"asdfasdf\"],"\"ao : [{"\"a:1,"\"b:2,"\"c:\"asdf\""\"}]"\"}";value_object vo1;std::stringstream ss;vo1.parse_string(json_str);vo1.to_string(ss);value_object vo2;vo2.parse_string(ss.str());assert(vo1 == vo2);}return 0;}

测试结果

{ta:1,tb:6.248,ts:"haha, object"},{ta:0,tb:0,ts:""},old_obj = {ta:1,tb:6.248,ts:"haha, object"}new_obj = {ta:2,tb:3.1415,ts:"hi test"}{"aa":1,"v1":[{"ta":1,"tb":6.248,"ts":"haha, object"},{"ta":0,"tb":0,"ts":""}],"obj_array":[{"ta":1,"tb":6.248,"ts":"haha, object"},{"ta":0,"tb":0,"ts":""}],"int_array":[1,2,3,4,5,6,7],"int":0,"double":3.1425,"string":"hi test","obj1":{"ta":2,"tb":3.1415,"ts":"hi test"},"ta":2,"tb":3.1415,"ts":"hi test","a":1,"b ":2,"c":"asdf\"asdf","ab":[1,2,3,4,"asdfasdf"],"ao":[{"a":1,"b":2,"c":"asdf"}]}




0 0
原创粉丝点击