JSON 解析器

    本方法相当暴力和简单,暂时不能解析数组,不过就可用性而言,在简单的应用场合还是可以胜任的。此解析器是专为 Avatar 引擎设计的,以供实现编辑器

上代码:

//================================================
// Copyright (c) 2016 周仁锋. All rights reserved.
// ye_luo@qq.com
//================================================
#ifndef _CJSONPARSER_H_
#define _CJSONPARSER_H_
#include <string>
#include <unordered_map>
using namespace std;

/**
* JSON 解析器,仅能解析简单对象
*/
class CJsonParser {
public:
	CJsonParser();

	//! 解析文本
	bool Parse(const char* content);
	//! 获取指定键的值
	bool GetValue(const string& key, bool* value);
	bool GetValue(const string& key, int* value);
	bool GetValue(const string& key, float* value);
	bool GetValue(const string& key, char* value, int size);

private:
	//! json 值泛定义
	typedef struct _SValue {
		enum EType { NIL, BOOL, INT, FLOAT, STRING };
		EType type;
		int length;
		union {
			bool bValue;
			int iValue;
			float fValue;
			const char* sValue;
		};
	} SValue;

private:
	//! 解析值
	SValue CJsonParser::ParseValue(const char* content, int size, int* offset);

private:
	//! json 字符串长度
	int m_iContentLen;
	//! json 字符串
	const char* m_pContent;
	//! 解析完的键值对
	unordered_map<string, SValue> m_mapKeyValue;
};

#endif
C++实现部分如下

//================================================
// Copyright (c) 2016 周仁锋. All rights reserved.
// ye_luo@qq.com
//================================================
#include "CJsonParser.h"
#include <vector>
using namespace std;

/**
* 构造函数
*/
CJsonParser::CJsonParser() {
	m_pContent = 0;
	m_iContentLen = 0;
}

/**
* 解析文本
*/
bool CJsonParser::Parse(const char* content) {
	m_pContent = content;
	m_iContentLen = 0;
	while (m_pContent[m_iContentLen]) {
		m_iContentLen++;
	}
	m_mapKeyValue.clear();
	// 找到开始与结束位置
	int indexBeg = 0;
	int indexEnd = m_iContentLen - 1;
	while (m_pContent[indexBeg++] != '{' && indexBeg < m_iContentLen);
	while (m_pContent[indexEnd--] != '}' && indexEnd > 0);
	if (indexBeg > indexEnd) return false;
	// 解析键值对
	while (indexBeg < indexEnd) {
		int index1 = indexBeg;
		while (index1 < indexEnd && m_pContent[index1++] != '"');
		int index2 = index1;
		while (index2 < indexEnd && m_pContent[++index2] != '"');
		if (index1 < index2) {
			string key = string().append(&m_pContent[index1], index2 - index1);
			index1 = index2 + 1;
			SValue value = ParseValue(&m_pContent[index1], indexEnd - index2, &index2);
			indexBeg = index1 + index2;
			m_mapKeyValue.insert(pair<string, SValue>(key, value));
		}
	}
	return true;
}

/**
* 获取指定键的值
*/
bool CJsonParser::GetValue(const string& key, bool* value) {
	unordered_map<string, SValue>::const_iterator got = m_mapKeyValue.find(key);
	if (got == m_mapKeyValue.end()) return false;
	if (got->second.type != SValue::BOOL) return false;
	value[0] = got->second.bValue;
	return true;
}

/**
* 获取指定键的值
*/
bool CJsonParser::GetValue(const string& key, int* value) {
	unordered_map<string, SValue>::const_iterator got = m_mapKeyValue.find(key);
	if (got == m_mapKeyValue.end()) return false;
	if (got->second.type != SValue::INT) return false;
	value[0] = got->second.iValue;
	return true;
}

/**
* 获取指定键的值
*/
bool CJsonParser::GetValue(const string& key, float* value) {
	unordered_map<string, SValue>::const_iterator got = m_mapKeyValue.find(key);
	if (got == m_mapKeyValue.end()) return false;
	if (got->second.type != SValue::FLOAT) {
		if (got->second.type == SValue::INT) {
			value[0] = (float)got->second.iValue;
			return true;
		} else return false;
	}
	value[0] = got->second.fValue;
	return true;
}

/**
* 获取指定键的值
*/
bool CJsonParser::GetValue(const string& key, char* value, int size) {
	unordered_map<string, SValue>::const_iterator got = m_mapKeyValue.find(key);
	if (got == m_mapKeyValue.end()) return false;
	if (got->second.type != SValue::STRING) return false;
	if (got->second.length < size - 1) size = got->second.length;
	else size = size - 1;
	for (int i = 0; i < size; i++) {
		value[i] = got->second.sValue[i];
	}
	value[size] = '\0';
	return true;
}

/**
* 解析值
*/
CJsonParser::SValue CJsonParser::ParseValue(const char* content, int size, int* offset) {
	int index = 0;
	// 设置默认值
	SValue value;
	value.type = SValue::NIL;
	value.length = 0;
	*offset = size;
	// 解析字符串
	while (index < size) {
		const char ch = content[index];
		// 对象类型
		if (ch == '{') {
			int position = index + 1;
			vector<char> keyStack;
			keyStack.push_back('{');
			while (position < size) {
				const char c = content[position];
				const char top = keyStack.back();
				if (c == '\\') position++;
				else if (c == '{') {
					if (top != '"') keyStack.push_back('{');
				}
				else if (c == '}') {
					if (top == '{') keyStack.pop_back();
					if (keyStack.size() == 0) break;
				}
				else if (c == '"') {
					if (top == '"') keyStack.pop_back();
					else keyStack.push_back('"');
				}
				position++;
			}
			*offset = position;
			if (keyStack.size() == 0) {
				value.type = SValue::STRING;
				value.length = position - index + 1;
				value.sValue = content + index;
			}
			break;
		}
		// 字符串类型
		else if (ch == '"') {
			int position = index + 1;
			while (position < size) {
				const char c = content[position];
				if (c == '\\') position++;
				else if (c == '"') break;
				position++;
			}
			value.type = SValue::STRING;
			value.length = position - index - 1;
			value.sValue = content + index + 1;
			*offset = position + 1;
			break;
		}
		// 布尔类型 true
		else if (ch == 't' || ch == 'T') {
			if (index + 3 >= size) break;
			const char c1 = content[index + 1];
			const char c2 = content[index + 2];
			const char c3 = content[index + 3];
			if ((c1 == 'r' || c1 == 'R') &&
				(c2 == 'u' || c2 == 'U') &&
				(c3 == 'e' || c3 == 'E')) {
				value.type = SValue::BOOL;
				value.bValue = true;
				*offset = index + 4;
				break;
			}
		}
		// 布尔类型 false
		else if (ch == 'f' || ch == 'F') {
			if (index + 4 >= size) break;
			const char c1 = content[index + 1];
			const char c2 = content[index + 2];
			const char c3 = content[index + 3];
			const char c4 = content[index + 4];
			if ((c1 == 'a' || c1 == 'A') &&
				(c2 == 'l' || c2 == 'L') &&
				(c3 == 's' || c3 == 'S') &&
				(c4 == 'e' || c4 == 'E')) {
				value.type = SValue::BOOL;
				value.bValue = false;
				*offset = index + 5;
				break;
			}
		}
		// 整型或者浮点型
		else if (ch >= '0' && ch <= '9') {
			int position = index;
			bool isFloat = false;
			while (position < size) {
				const char c = content[position];
				if (c == 'e' || c == 'E' || c == '.') isFloat = true;
				else if (c < '0' || c > '9') break;
				position++;
			}
			const char sign = content[index - 1];
			if (sign == '-' || sign == '+') index -= 1;
			char temp[32] = {0};
			for (int i = 0; i < position - index && i < 32; i++) {
				temp[i] = content[i + index];
			}
			if (isFloat) {
				value.type = SValue::FLOAT;
				value.fValue = (float)atof(temp);
			} else {
				value.type = SValue::INT;
				value.iValue = atoi(temp);
			}
			*offset = position;
			break;
		}
		index++;
	}
	return value;
}

工作原理:解析字符串,将键值对插入 m_mapKeyValue 中(对于 string 类型的值没有申请内存,直接使用源字符串,通过指针和长度进行定位)

使用方法:

const char* str = "{\"bValue\":false,\"iValue\":100,\"fValue\":0.12,\"strValue\":\"hello\",\"object\":{\"which\":0,\"finish\":true}}";
CJsonParser parser;
parser.Parse(str);

bool success;
bool bValue;
int iValue;
float fValue;
char strValue[100];
char objValue[200];
success = parser.GetValue("bValue", &bValue);
success = parser.GetValue("iValue", &iValue);
success = parser.GetValue("fValue", &fValue);
success = parser.GetValue("strValue", strValue, 100);
success = parser.GetValue("object", objValue, 200);
success = parser.Parse(objValue);
success = parser.GetValue("which", &iValue);
success = parser.GetValue("finish", &bValue);

没测过解析的速度,我想应该很快,毕竟方法足够简单

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值