起因
遇到一个情况,在一个字符串中包含了多个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, 如果要使用请注意版权声明。
在代码受控的仓库中有使用示例。