从复合字符串中分割并解析多个JSON字符串
起因
遇到一个情况,在一个字符串中包含了多个json字符串,在后续的处理中需要将其分解开,分成多个独立的json字符串。
在网上找了一下没有找到比较好的处理方法,那么决定自己写一个。
分析
首先,json是通过 {} 包裹的,并且是可以嵌套的。因此,从第一个 { 开始,遇到与左右大括号相等的数量时候,认为是截取出来一个json字符串。
其次,上面的情况是一种理想状态,因为json字符串中的key或者value中是可能也存在"{“和”}"的,需要排除这种状况,也就是遇到在key或者value中的情况是不能将其当做分隔符号的。那么需要通过分析,将key或者value本身是字符串,且忽略内部的大括号。
再次,分割key和value的字符串的时候,其使用单双引号包围,需要排除是单双引号转义的情况。
最后,收集每个json字符串中间的内容,则能够将其分解开。
代码实现
解析字符串时候,分为三种状态,使用枚举值,如下所示:
enum class ParseStage
{
FIND_START_TAG,
PARSING_JSON,
PARSING_STRING
};
分割的代码如下:
// jsons -- 分割后的结果
// jsonStr -- 输入的原始字符串
std::vector<std::string> jsons;
std::string tmpJson;
ParseStage parseStage = ParseStage::FIND_START_TAG;
int tagNextIndex = 0;
char lastChar = '\0';
char stringSpliter = '\0';
bool resetLastCheckChar = false;
for (const char& tmpChar : jsonStr) {
if(parseStage == ParseStage::FIND_START_TAG)
{
if(tmpChar == '{')
{
parseStage = ParseStage::PARSING_JSON;
tmpJson += tmpChar;
tagNextIndex = 1;
}
}
else if(parseStage == ParseStage::PARSING_JSON)
{
tmpJson += tmpChar;
if(tmpChar == '{')
{
tagNextIndex ++;
}
if(tmpChar == '}')
{
tagNextIndex --;
}
if(tagNextIndex == 0)
{
jsons.emplace_back(tmpJson);
parseStage = ParseStage::FIND_START_TAG;
tmpJson.clear();
}
if(tmpChar == '\'' || tmpChar == '"')
{
stringSpliter = tmpChar;
parseStage = ParseStage::PARSING_STRING;
}
}
else if(parseStage == ParseStage::PARSING_STRING)
{
tmpJson += tmpChar;
if(tmpChar == '\\' && lastChar == '\\')
{
resetLastCheckChar = true;
}
if(tmpChar == stringSpliter && lastChar != '\\')
{
parseStage = ParseStage::PARSING_JSON;
}
}
else
{
; // do nothing
}
if(!resetLastCheckChar)
{
lastChar = tmpChar;
}
else
{
lastChar = '\0';
}
}
代码受控地址与版权
以上代码是MIT协议,代码受控在Github https://github.com/chinanewer/SimpleJsonSplitter.git, 如果要使用请注意版权声明。
在代码受控的仓库中有使用示例。