JSON 解析器

来源:互联网 发布:风控系统源码 编辑:程序博客网 时间:2024/05/22 03:44

    本方法相当暴力和简单,暂时不能解析数组,不过就可用性而言,在简单的应用场合还是可以胜任的。此解析器是专为 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;}// 布尔类型 trueelse 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;}}// 布尔类型 falseelse 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