基于C++简易JSON解析器

本文介绍了一个正在开发中的JSON解析器类的设计与实现细节,包括如何处理JSON字符串中的各种元素,如对象、数组、字符串等,并提供了详细的代码示例。

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

翻译自Java原版

 正在开发测试中,先贴上Parser类代码。

class JsonParser {
	private:
		char COLON = ':';
	public:
		JsonParser() {} 

		void* parse() {
			CharsRange trimmedJson = CharsRange::newRange(0, jsonStr.size()).trim();
			return processValue(trimmedJson);
		}

		map<string, void*> processPlainObject(CharsRange range) {
			list<Property> properties = processProperties(CharsRange::newRange(range.start + 1, range.end - 1));
			map<string, void*> objectMap;
			list<Property>::iterator prop;
			for(prop = properties.begin() ; prop != properties.end() ; prop++) {
				objectMap.insert(pair<string, void *>(prop->name, prop->value));
			}
			return objectMap;
		}

		list<Property> processProperties(CharsRange range) {
			list<Property> properties;
			int nameStartMark = range.start;
			for (int curPos = range.start; curPos < range.end; curPos++) {
				char ch = jsonStr.at(curPos);
				if (ch == COLON) {
					CharsRange nameToken = CharsRange::newRange(nameStartMark, curPos).trim();
					int readCursor = 0;
					void* value = genValue(range, ++curPos, &readCursor);
					curPos = readCursor + 1;
					nameStartMark = curPos;
					string name = genName(nameToken);
					properties.push_back(Property::of(name, value));
				}
			}
			return properties;
		}

		void* genValue(CharsRange range, int curPos, int *readCursor) {
			CharsRange valueSegment = findNextValue(CharsRange::newRange(curPos, range.end), readCursor);
			return processValue(valueSegment);
		}

		string genName(CharsRange nameToken) {
			bool hasQuote = jsonStr.at(nameToken.start) == '"' || jsonStr.at(nameToken.end) == '"';
			int start = hasQuote ? nameToken.start + 1 : nameToken.start;
			int end = hasQuote ? nameToken.end - 1 : nameToken.end;
			return CharsRange::newRange(start, end).toString();
		}

		list<void*> processArray(CharsRange range) {
			return processElements(CharsRange::newRange(range.start + 1, range.end - 1));
		}

		list<void*> processElements(CharsRange range) {
			list<void*> objList;
			int elementStartMark = range.start;
			for (int i = range.start; i < range.end; i++) {
				int readCursor = 0;
				void * elementValue = genValue(range, elementStartMark, &readCursor);
				objList.push_back(elementValue);
				i = readCursor;
				elementStartMark = i + 1;
			}
			return objList;
		}

		/**
		 * @param chars
		 * @return value segment trimmed.
		 */
		CharsRange findNextValue(CharsRange chars, int *readCursor) {
			CharsRange trimChars = chars.trimLeft();
			if (trimChars.relativeChar(0) == '{') {
				return completeSymbolPair(trimChars, readCursor, "{}");
			} else if (trimChars.relativeChar(0) == '[') {
				return completeSymbolPair(trimChars, readCursor, "[]");
			} else {
				int i;
				for (i = trimChars.start + 1; i < trimChars.end; i++) {
					char ch = jsonStr.at(i);
					if (ch == ',') {
						break;
					}
				}
				readCursor = &i;
				return CharsRange::newRange(trimChars.start, i).trim();
			}
		}

		CharsRange completeSymbolPair(CharsRange trimChars, int *readCursor, string symbolPair) {
			int leftSymbol = symbolPair.at(0);
			int rightSymbol = symbolPair.at(1);
			int symbolsScore = 1;
			int i;
			CharsRange valueSegment(0,0);
			for (i = trimChars.start + 1; i < trimChars.end; i++) {
				char ch = jsonStr.at(i);
				if (ch == leftSymbol) {
					symbolsScore++;
				} else if (ch == rightSymbol) {
					symbolsScore--;
				}
				if (symbolsScore == 0) {
					valueSegment = CharsRange::newRange(trimChars.start, i + 1);
					break;
				}
			}
			for (; i < trimChars.end; i++) {
				char chx = jsonStr.at(i);
				if (chx == ',') {
					break;
				}
			}
			readCursor = &i;
			return valueSegment;
		}

		void* processValue(CharsRange valueSegment) {
			void* value;
			if (valueSegment.relativeChar(0) == '"') {
				string rng = CharsRange::newRange(valueSegment.start + 1, valueSegment.end - 1).toString().data();
				value = &rng;
			} else if (valueSegment.relativeChar(0) == '{') {
				map<string, void*> obj = processPlainObject(valueSegment);
				value = &obj;
			} else if (valueSegment.relativeChar(0) == '[') {
				list<void*> objLst = processArray(valueSegment);
				value = &objLst;
			} else if (valueSegment.equalsString("true")) {
				bool ret = true;
				value = &ret;
			} else if (valueSegment.equalsString("false")) {
				bool ret = false;
				value = &ret;
			} else if (valueSegment.equalsString("null")) {
				value = NULL;
			} else {
				int ret = atoi(valueSegment.toString().data());
				value = &ret;
			}
			return value;
		}
};

 

JSON++ Build Status Introduction JSON++ is a light-weight JSON parser, writer and reader written in C++. JSON++ can also convert JSON documents into lossless XML documents. Contributors http://github.com/hjiang http://github.com/elanthis http://github.com/r-lyeh If you've made substantial contribution, please add your link here. Why another JSON parser? Perhaps because web service clients are usually written in dynamic languages these days, none of the existing C++ JSON parsers fitted my needs very well, so I wrote one that I used in another project. My goals for JSON++ were: Efficient in both memory and speed. No third party dependencies. JSON++ only depends on the standard C++ library. Cross platform. Robust. Small and convenient API. Most of the time, you only need to call one function and two function templates. Easy to integrate. JSON++ only has one source file and one header file. Just compile the source file and link with your program. Able to construct documents dynamically. JSON writer: write documents in JSON format. Other contributors have sinced added more functionalities: XML writer: convert documents to JSONx format. See http://goo.gl/I3cxs for details. XML writer: convert documents to JXML format. See https://github.com/r-lyeh/JXML for details. XML writer: convert documents to JXMLex format. See https://github.com/r-lyeh/JXMLex for details. XML writer: convert documents to tagged XML format. See https://github.com/hjiang/jsonxx/issues/12 for details. Compiler version You need a modern C++ compiler. For older compilers, please try legacy branch. Configuration Strict/permissive parsing JSONxx can parse JSON documents both in strict or permissive mode. When jsonxx::Settings::Parser is set to Strict, JSONxx parser will accept: Fully conformant JSON documents only. When jsonxx::Settings::Parser is set to Permissive, JSONxx parser will accept: Fully conformant JSON documents Ending commas in arrays and objects: { "array": [0,1,2,], } Single quoted strings: ['hello', "world"] C++ style comments: { "width": 320, "height": 240 } //Picture details Default value is Permissive. When jsonxx::Settings::UnquotedKeys is set to Enabled, JSONxx parser will accept: Unquoted keys: {name: "world"} Default value is Disabled. Assertions JSONxx uses internally JSONXX_ASSERT(...) macro that works both in debug and release mode. Set jsonxx::Settings::Assertions value to Disabled to disable assertions. Default value is Enabled. Usage The following snippets are from one of the unit tests. They are quite self-descriptive. using namespace std; using namespace jsonxx; string teststr( "{" " \"foo\" : 1," " \"bar\" : false," " \"person\" : {\"name\" : \"GWB\", \"age\" : 60,}," " \"data\": [\"abcd\", 42]," "}" ); // Parse string or stream Object o; assert(o.parse(teststr)); // Validation. Checking for JSON types and values as well assert(1 == o.get<Number>("foo")); assert(o.has<Boolean>("bar")); assert(o.has<Object>("person")); assert(o.get<Object>("person").has<Number>("age")); assert(!o.get<Object>("person").has<Boolean>("old")); assert(o.get<Object>("person").get<Boolean>("old", false)); assert(o.has<Array>("data")); assert(o.get<Array>("data").get<Number>(1) == 42); assert(o.get<Array>("data").get<String>(0) == "abcd"); assert(o.get<Array>("data").get<String>(2, "hello") == "hello"); assert(!o.has<Number>("data")); cout << o.json() << endl; // JSON output cout << o.xml(JSONx) << endl; // JSON to XML conversion (JSONx subtype) cout << o.xml(JXML) << endl; // JSON to XML conversion (JXML subtype) cout << o.xml(JXMLex) << endl; // JSON to XML conversion (JXMLex subtype) // Generate JSON document dynamically using namespace std; using namespace jsonxx; Array a; a << 123; a << "hello world"; a << 3.1415; a << 99.95f; a << 'h'; a << Object("key", "value"); Object o; o << "key1" << "value"; o << "key2" << 123; o << "key3" << a; cout << o.json() << endl; To do Custom JSON comments (C style /**/) when permissive parsing is enabled.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值