[JSON文件解析]用纯c++的方法解析JSON文件

JSON文件是指那些以".json"为后缀的,这些文件内容有一些共同的特点。

1.关键字以英文的引号为标记如, " xxxx"的xxxx就是一个关键字

2.关键字面一定会跟英文的冒号:和大括号 {

3.参数一般的形式为  "参数名" :"字符参数","参数名":数值,这两种

4.list一定后面存在中括号 [

5.结尾一定能找到对应的括号。

那么剩下的就简单了,如何根据以上特征,去解读json文件呢?

为了加深印象这里只贴一些关键函数的代码(PS:断断续续写了三天勉强能用)

第一步首先是头文件

	enum KEY//这个是关键字的一些操作
	{
		QUOTATION=0,
		COLON=1,
		LEFT_BRACKET,
		RIGHT_BRACKET,
		LEFT_BRACES,
		RIGHT_BRACES,
		POINT
	};

	typedef struct _JsonKey
	{
		string BaseName;
		string KeyName;
		int    BeginLineNo;
		int    EndLineNo;
	}JsonKey;
public:
    BOOL ReadJsonFile(string filepath);//加载json文件
	int GetKeyWordPos(KEY key,string LineWord,int SrcLen);//输入的是substr
	int GetKeyWordPos(KEY key, string LineWord);//输入的是原字符
private:
	//1.第一次解析分析,关键字,数组,值等等
	BOOL GetKeyWord(map<int, string> &bKeyMap, map<string, int>&ParaKeyMap, map<int, string>&ParaValueMap, map<int, string>&ListMap);
	//2.第二次分析,构造JsonKey
	BOOL GetKeyWord2();
protected:
	vector<string> m_nData;//总的数据
	map<int, string> m_nKeyMap;//关键字,行
	map<string, int> m_nParaKeyMap;//参数名,行
	map<int, string> m_ParaValueMap;//参数值,行
	map<int, string> m_nListMap;//list
	JsonKey         *m_nJsonKey;
protected:
	int m_nLineCount;//行数

第二步,具体实现

//ReadJsonFile
BOOL CJsonOperate::ReadJsonFile(string filepath)
{
	//后缀判断
	int p = GetKeyWordPos(KEY::POINT, filepath);
	if (p<0)
	{
		AfxMessageBox("The path is Error!!!");
		return FALSE;
	}
	else
	{
		int n = filepath.length() - 1 - p;
		string bStr = filepath.substr(p + 1, n);
		if (bStr!="json")
		{
			AfxMessageBox("The File is is not JSON file!!!");
			return FALSE;
		}
	}
   
	char *pPath = new char[filepath.length()+1];//+1:防止越界
	memset(pPath, NULL, sizeof(char)*filepath.length());
	strcpy(pPath, filepath.c_str());//转换一下
	
	ifstream Cfile(pPath);
	if (!Cfile.is_open())
	{
		AfxMessageBox("Error: Open file failed!!!");
		delete[] pPath;
		return FALSE;
	}
	else
	{
		m_nData.clear();
	}
	string data;
	while (getline(Cfile, data))
	{
		m_nData.push_back(data);//先把说有的数据读出来
	}
	m_nLineCount = m_nData.size();
	if (m_nLineCount<1)
	{
		AfxMessageBox("Error: The File is NULL!!!");
		return FALSE;
	}
	Cfile.close();

	GetKeyWord(m_nKeyMap, m_nParaKeyMap, m_ParaValueMap,m_nListMap);
	GetKeyWord2();
	delete[] pPath;

	return TRUE;
}
BOOL CJsonOperate::GetKeyWord(map<int, string>&bKeyMap, map<string, int>&ParaMap, map<int, string>&ParaValueMap,map<int, string>&ListMap)
{
	//substr(起始位,位数)
	bool test = true;

	bKeyMap.clear();
	ParaMap.clear();
	ParaValueMap.clear();
	ListMap.clear();

	int nPos = 0;
	if (m_nData.size()==0)
	{
		AfxMessageBox("Error:data is NULL");
	}
	for (int i = 0; i < m_nLineCount;i++)
	{
		//找左边引号
		if (test)
		{
			string data = m_nData.at(i);
		}
		int pos = GetKeyWordPos(KEY::QUOTATION, m_nData.at(i),m_nData.at(i).length());
		if (pos<0)
		{
			continue;
		}
		//找右边引号
		if (test)
		{
			string data = m_nData.at(i).substr(pos + 1, m_nData.at(i).size() - pos);
		}
		int pos1 = GetKeyWordPos(KEY::QUOTATION, m_nData.at(i).substr(pos + 1, m_nData.at(i).size() - pos), m_nData.at(i).length());
		if (pos1<0)
		{
			continue;
		}
		//已经找到Key
		//
		//分析key的周围先找冒号
		if (test)
		{
			string data = m_nData.at(i).substr(pos1 + 1, m_nData.at(i).size() - pos1);
		}
		int pos2 = GetKeyWordPos(KEY::COLON, m_nData.at(i).substr(pos1 + 1, m_nData.at(i).size() - pos1), m_nData.at(i).length());
		if (pos2>=0)
		{
			//说明是有,再找{
			if (test)
			{
				string data = m_nData.at(i).substr(pos2 + 1, m_nData.at(i).size() - pos2);
			}
			int pos3 = GetKeyWordPos(KEY::LEFT_BRACES, m_nData.at(i).substr(pos2 + 1, m_nData.at(i).size() - pos2), m_nData.at(i).length());
			if (pos3>=0)
			{
				//key
				bKeyMap.insert(pair<int, string>(i, m_nData.at(i).substr(pos + 1, pos1-pos-1)));
				//在这里还需要一个反馈验证,用于验证分组

			}
			else
			{
				//没有,先判断是来到List还是Para,有[代表是list,没有代表参数区
				int pos6 = GetKeyWordPos(KEY::LEFT_BRACKET, m_nData.at(i).substr(pos2 + 1, m_nData.at(i).size() -pos2), m_nData.at(i).length());
				if (pos6>0)
				{
					//list
					ListMap.insert(pair<int, string>(i, m_nData.at(i).substr(pos + 1, pos1-pos-1)));
				}
				else
				{
					ParaMap.insert(pair<string, int>(m_nData.at(i).substr(pos + 1, pos1-pos-1), i));
					//再去找参数
					string bbb = m_nData.at(i).substr(pos2 + 1, m_nData.at(i).size() - 1);
					int pos4 = GetKeyWordPos(KEY::QUOTATION, m_nData.at(i).substr(pos2 + 1, m_nData.at(i).size() - pos2), m_nData.at(i).length());
					if (pos4 >= 0)//从string和数值
					{
						bbb = m_nData.at(i).substr(pos4 + 1, m_nData.at(i).size() - pos4);
						int pos5 = GetKeyWordPos(KEY::QUOTATION, m_nData.at(i).substr(pos4+1, m_nData.at(i).size() - pos4), m_nData.at(i).length());
						//paravalue
						ParaValueMap.insert(pair<int, string>(i, m_nData.at(i).substr(pos4+1, pos5-pos4-1)));
					}
					else
					{
						nPos = pos2;
						int n = m_nData.at(i).size() - 1 - (nPos + 1);
						ParaValueMap.insert(pair<int, string>(i, m_nData.at(i).substr(nPos + 1, n)));
					}

				}
			
			
				
			}
		}
	}
	if (bKeyMap.size() == 0 || ParaMap.size() == 0 || ParaValueMap.size() == 0 || ListMap.size() == 0)
	{
		AfxMessageBox("Error: No KeyWord");
		bKeyMap.clear();
		ParaMap.clear();
		ParaValueMap.clear();
		ListMap.clear();
		return FALSE;
	}
	return TRUE;
}
int CJsonOperate::GetKeyWordPos(KEY key, string LineWord,int StrLen)
{
	char bKey;
	int pos = -1;
	if (key == KEY::QUOTATION)
	{
		bKey = '\"';
	}else if (key == KEY::COLON)
	{
		bKey = ':';
	}
	else if (key == KEY::LEFT_BRACKET)
	{
		bKey = '[';
	}
	else if (key == KEY::RIGHT_BRACKET)
	{
		bKey = ']';
	}else if (key==KEY::POINT)
	{
		bKey = '.';
	}
	else if (key==KEY::LEFT_BRACES)
	{
		bKey = '{';
	}
	else if (key == KEY::RIGHT_BRACES)
	{
		bKey = '}';
	}
	size_t p = LineWord.find(bKey);
	pos = static_cast<int>(p);
	if (LineWord.length()<StrLen)
	{
		if (pos>-1)
		{
			pos += (StrLen - LineWord.length());
		}
		
	}
	return pos;
}
int CJsonOperate::GetKeyWordPos(KEY key, string LineWord)
{
	char bKey;
	int pos = -1;
	if (key == KEY::QUOTATION)
	{
		bKey = '\"';
	}
	else if (key == KEY::COLON)
	{
		bKey = ':';
	}
	else if (key == KEY::LEFT_BRACKET)
	{
		bKey = '[';
	}
	else if (key == KEY::RIGHT_BRACKET)
	{
		bKey = ']';
	}
	else if (key == KEY::POINT)
	{
		bKey = '.';
	}
	else if (key == KEY::LEFT_BRACES)
	{
		bKey = '{';
	}
	else if (key == KEY::RIGHT_BRACES)
	{
		bKey = '}';
	}
	size_t p = LineWord.find(bKey);
	pos = static_cast<int>(p);
	return pos;
}

最后,GetKeyWord2()这个是核心问题,应该怎么实现呢,下面给出部分代码

BOOL CJsonOperate::GetKeyWord2()
{
	if (m_nKeyMap.size() == 0)
	{
		AfxMessageBox("Error: No KeyWord");
		m_nKeyMap.clear();
		return FALSE;
	}
	//1.创建数组,赋值
	int n = 0;
	int nKeyNum = m_nKeyMap.size();
	m_nJsonKey = new JsonKey[nKeyNum];
	map<int, string>::iterator iter;
	for (int i = 0; i < m_nLineCount;i++)
	{
		iter = m_nKeyMap.find(i);
		if (iter != m_nKeyMap.end())
		{
			m_nJsonKey[n].BaseName = "";
			m_nJsonKey[n].KeyName = iter->second;
			m_nJsonKey[n].BeginLineNo = i;
			m_nJsonKey[n].EndLineNo = 0;
			n++;
		}
	}
	//2.对数组进行求解,还是把源码放上去吧
   string bBase;
	for (int j = 0; j < nKeyNum;j++)
	{
		int Left_Num = 1;
		int Right_Num = 0;
		string bStr;
		for (int i = 0; i < m_nLineCount - m_nJsonKey[j].BeginLineNo;i++)
		{
			int p = GetKeyWordPos(KEY::RIGHT_BRACES, m_nData.at(m_nJsonKey[j].BeginLineNo + 1+i));
			if (p > -1)
			{
				Right_Num++;
			}
			else
			{
				int p = GetKeyWordPos(KEY::LEFT_BRACES, m_nData.at(m_nJsonKey[j].BeginLineNo + 1 + i));
				if (p > -1)
				{
					Left_Num++;
				}

			}
			if (Left_Num == Right_Num)
			{
				m_nJsonKey[j].EndLineNo = m_nJsonKey[j].BeginLineNo + 1 + i;
				if (j>0)
				{
					//找他上面endlineno最大的
					int Max=j;
					for (int z = j; z > 0;z--)
					{
						if (m_nJsonKey[j].EndLineNo<m_nJsonKey[z-1].EndLineNo)
						{
							Max = z - 1;
						}
					}

					m_nJsonKey[j].BaseName = m_nJsonKey[Max].KeyName;
				}
				else
				{
					m_nJsonKey[j].BaseName = m_nJsonKey[j].KeyName;
				}
				break;
			}

		}
	}

   
}

有大神有更好的办法的话请指正谢谢!

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值