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

博主分享了自己在C++中实现JSON解析器的过程,尽管使用了一些技巧但仍感到不甚满意,代码作为学习资料供读者参考。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 repeat
			if(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_op
	protected:
		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"}]}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值