本方法相当暴力和简单,暂时不能解析数组,不过就可用性而言,在简单的应用场合还是可以胜任的。此解析器是专为 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);
没测过解析的速度,我想应该很快,毕竟方法足够简单