JSON 解析器(升级版)

之前写过一个JSON解析器,仅能解析简单对象,且不支持数组解析,这次进行改进升级。这个解析器遵从按需解析且不分配内存的原则。精简但是功能齐全,解析器的特点是快速,方便。详见代码:

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

/**
* @brief JSON 解析器
*/
class CJsonParser {
public:
	//! 默认构造函数
	CJsonParser();
	//! 指定字符串构造
	CJsonParser(const char* content);
	//! 使用指定长度的字符串构造
	CJsonParser(const char* content, int length);

	//! 解析指定字符串
	bool Parse(const char* content, int length);
	//! 判断是否包含指定值
	bool IsContain(const char* name);
	//! 获取数组节点数组大小
	int GetCount();

	//! 获取节点内指定名称的值
	CJsonParser GetValue(const char* name);
	//! 获取数组节点内指定的值
	CJsonParser GetValue(int index);

public:
	//! 是否为空节点
	bool IsEmpty() { return m_sValue.type == SValue::NIL; }
	//! 是否为布尔类型节点
	bool IsBool() { return m_sValue.type == SValue::BOOL; }
	//! 是否为数字类型节点
	bool IsNumber() { return m_sValue.type == SValue::NUMBER; }
	//! 是否为字符串类型节点
	bool IsString() { return m_sValue.type == SValue::STRING; }
	//! 是否为对象类型节点
	bool IsObject() { return m_sValue.type == SValue::OBJECT; }
	//! 是否为数组类型节点
	bool IsArray() { return m_sValue.type == SValue::ARRAY; }

	//! 转换为布尔类型
	bool AsBool() { return m_sValue.bValue; }
	//! 转换为整型类型
	int AsInt() { return (int)m_sValue.fValue; }
	//! 转换为浮点类型
	float AsFloat() { return m_sValue.fValue; }
	//! 转换为字符串类型
	string AsString() { return string().append(m_sValue.pValue, m_sValue.length); }

private:
	//! JSON 值泛定义
	typedef struct _SValue {
		enum { NIL, BOOL, NUMBER, STRING, OBJECT, ARRAY } type;
		int length;
		union {
			bool bValue;
			float fValue;
			const char* pValue;
		};
	} SValue;

	//! 解析当前元素
	bool Parse();
	//! 解析对象字符串
	void ParseObject(const char* data, int length);
	//! 解析数组字符串
	void ParseArray(const char* data, int length);
	//! 解析数字字符串
	void ParseNumber(const char* data, int length);
	//! 解析 JSON 值
	CJsonParser ParseValue(const char* data, int length);

private:
	//! JSON 值
	SValue m_sValue;
	//! JSON 内部子元素
	map<string, CJsonParser> m_mapValues;
	//! JSON 内部数组
	vector<CJsonParser> m_vecValues;
};

#endif
C++实现部分

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

/**
* 构造函数
*/
CJsonParser::CJsonParser() {
	m_sValue.type = SValue::NIL;
	m_sValue.length = 0;
	m_sValue.pValue = 0;
}

/**
* 构造函数
*/
CJsonParser::CJsonParser(const char* content) {
	m_sValue.length = strlen(content);
	m_sValue.pValue = content;
	Parse();
}

/**
* 构造函数
*/
CJsonParser::CJsonParser(const char* content, int length) {
	m_sValue.length = length;
	m_sValue.pValue = content;
	Parse();
}

/**
* 解析指定字符串
*/
bool CJsonParser::Parse(const char* content, int length) {
	m_sValue.length = length;
	m_sValue.pValue = content;
	m_mapValues.clear();
	m_vecValues.clear();
	return Parse();
}

/**
* 判断是否包含指定值
*/
bool CJsonParser::IsContain(const char* name) {
	return m_mapValues.find(name) != m_mapValues.end();
}

/**
* 获取数组节点数组大小
*/
int CJsonParser::GetCount() {
	return m_vecValues.size();
}

/**
* 获取节点内指定名称的值
*/
CJsonParser CJsonParser::GetValue(const char* name) {
	if (m_sValue.type == SValue::OBJECT) {
		map<string, CJsonParser>::iterator iter = m_mapValues.find(name);
		if (iter != m_mapValues.end()) {
			iter->second.Parse();
			return iter->second;
		}
	}
	return CJsonParser();
}

/**
* 获取数组节点内指定的值
*/
CJsonParser CJsonParser::GetValue(int index) {
	if (m_sValue.type == SValue::ARRAY) {
		if (index >= 0 && index < (int)m_vecValues.size()) {
			m_vecValues[index].Parse();
			return m_vecValues[index];
		}
	}
	return CJsonParser();
}

/**
* 解析当前元素
*/
bool CJsonParser::Parse() {
	m_sValue.type = SValue::NIL;
	int beg = 0;
	int end = m_sValue.length - 1;
	const char* data = m_sValue.pValue;
	while (data[beg] == ' ' || data[beg] == '\t' || data[beg] == '\r' || data[beg] == '\n') ++beg;
	while (data[end] == ' ' || data[end] == '\t' || data[end] == '\r' || data[end] == '\n') --end;
	if (beg >= end) return false;
	// 依次判断类型
	if (data[beg] == '{' && data[end] == '}') {
		m_sValue.type = SValue::OBJECT;
		m_sValue.length = end - beg + 1;
		ParseObject(data + beg, m_sValue.length);
		return true;
	}
	if (data[beg] == '[' && data[end] == ']') {
		m_sValue.type = SValue::ARRAY;
		m_sValue.length = end - beg + 1;
		ParseArray(data + beg, m_sValue.length);
		return true;
	}
	if (data[beg] == '-' || (data[beg] >= '0' && data[beg] <= '9')) {
		m_sValue.type = SValue::NUMBER;
		m_sValue.length = end - beg + 1;
		ParseNumber(data + beg, m_sValue.length);
		return true;
	}
	if (data[beg] == '"' && data[end] == '"') {
		m_sValue.type = SValue::STRING;
		m_sValue.length = end - beg - 1;
		m_sValue.pValue = &data[beg + 1];
		return true;
	}
	if ((data[beg + 0] == 't' || data[beg + 0] == 'T') &&
		(data[beg + 1] == 'r' || data[beg + 1] == 'R') &&
		(data[beg + 2] == 'u' || data[beg + 2] == 'U') &&
		(data[beg + 3] == 'e' || data[beg + 3] == 'E')) {
		m_sValue.type = SValue::BOOL;
		m_sValue.length = 0;
		m_sValue.bValue = true;
		return true;
	}
	if ((data[beg + 0] == 'f' || data[beg + 0] == 'F') &&
		(data[beg + 1] == 'a' || data[beg + 1] == 'A') &&
		(data[beg + 2] == 'l' || data[beg + 2] == 'L') &&
		(data[beg + 3] == 's' || data[beg + 3] == 'S') &&
		(data[beg + 4] == 'e' || data[beg + 4] == 'E')) {
		m_sValue.type = SValue::BOOL;
		m_sValue.length = 0;
		m_sValue.bValue = false;
		return true;
	}
	if ((data[beg + 0] == 'n' || data[beg + 0] == 'N') &&
		(data[beg + 1] == 'u' || data[beg + 1] == 'U') &&
		(data[beg + 2] == 'l' || data[beg + 2] == 'L') &&
		(data[beg + 3] == 'l' || data[beg + 3] == 'L')) {
		m_sValue.type = SValue::NIL;
		m_sValue.length = 4;
		m_sValue.pValue = &data[beg];
		return true;
	}
	return false;
}

/**
* 解析对象字符串
*/
void CJsonParser::ParseObject(const char* data, int length) {
	int index = 0;
	while (index < length) {
		while (index < length && data[index++] != '"');
		int nameOffset = index;
		while (index < length && data[index++] != '"');
		int nameSize = index - nameOffset - 1;
		if (nameSize > 0) {
			string name = string().append(&data[nameOffset], nameSize);
			while (data[index++] != ':');
			CJsonParser value = ParseValue(data + index, length - index);
			m_mapValues.insert(pair<string, CJsonParser>(name, value));
			index = value.m_sValue.pValue - data + value.m_sValue.length;
		}
	}
}

/**
* 解析数组字符串
*/
void CJsonParser::ParseArray(const char* data, int length) {
	int index = 1;
	length -= 1;
	while (index < length) {
		CJsonParser value = ParseValue(data + index, length - index);
		m_vecValues.push_back(value);
		index = value.m_sValue.pValue - data + value.m_sValue.length;
	}
}

/**
* 解析数字字符串
*/
void CJsonParser::ParseNumber(const char* data, int length) {
	char temp[256];
	length = length > 255 ? 255 : length;
	memcpy(temp, data, length);
	temp[length] = '\0';
	m_sValue.length = 0;
	m_sValue.fValue = (float)atof(temp);
}

/**
* 解析 JSON 值
*/
CJsonParser CJsonParser::ParseValue(const char* data, int length) {
	int pos = 0;
	while (data[pos] == ' ' || data[pos] == '\t' || data[pos] == '\r' || data[pos] == '\n' || data[pos] == ',') ++pos;
	int startPosition = pos;
	vector<char> keyStack;
	keyStack.push_back('#');
	while (pos < length) {
		const char key = data[pos++];
		const char top = keyStack.back();
		if (key == '\\') ++pos;
		else if (key == '"') {
			if (top == '"') keyStack.pop_back();
			else keyStack.push_back('"');
			if (keyStack.size() == 1) break;
		}
		else if (key == '{') {
			if (top != '"') keyStack.push_back('{');
		}
		else if (key == '[') {
			if (top != '"') keyStack.push_back('[');
		}
		else if (key == '}') {
			if (top == '{') keyStack.pop_back();
			if (keyStack.size() == 1) break;
		}
		else if (key == ']') {
			if (top == '[') keyStack.pop_back();
			if (keyStack.size() == 1) break;
		}
		else if (key == ',') {
			if (top == '#') --pos;
			if (keyStack.size() == 1) break;
		}
	}
	CJsonParser value;
	value.m_sValue.pValue = data + startPosition;
	value.m_sValue.length = pos - startPosition;
	return value;
}
解析示例代码

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

bool bValue = parser.GetValue("bValue").AsBool();
std::string strValue = parser.GetValue("strValue").AsString();
if (parser.IsContain("iValue")) {
	int iValue = parser.GetValue("iValue").AsInt();
}
if (parser.IsObject("object")) {
	int which = parser.GetValue("object").GetValue("which").AsInt();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值