使用nlohmann C++ JSON库时accept校验通过但parse报错的问题
json::accept()验证JSON有效,但parse()抛出解析异常的原因及解决方法
存储的JSON数据
[ { "Type":"SET", "routine":[ { "ID":"1", "InternalType":"Motorcycle", "payload":"2" }, { "ID":"12", "InternalType":"Chair" } ] }, { "Type":"GET", "routine":[ { "ID":"1", "InternalType":"Wheel" }, { "ID":"4", "InternalType":"Car", "payload":"6" } ] } ]
用于检查和解析的C++代码
#include<iostream> #include<fstream> #include"json.hpp" using json = nlohmann::json;; using namespace std; int main (){ string pathToFile = "/absolute/path/to/my/exampledata.json"; ifstream streamOfFile(pathToFile); if(!json::accept(streamOfFile)){ cout << "JSON NOT VALID!" << endl; } else { cout << "Nothing to complain about!" << endl; } try { json allRoutines = json::parse(streamOfFile); } catch (json::parse_error& error){ cerr << "Parse error at byte: " << error.byte << endl; } return 0; }
编译运行命令及结果
g++ myCode.cpp -o out ./out Nothing to complain about! Parse error at byte: 1
问题
根据官方文档,json::accept()函数在JSON数据有效时应返回true。但当前场景中,json::accept()对数据流返回true,实际调用json::parse()时却抛出了json::parse_error异常,需要指出使用错误、数据问题或解释该现象的原因。
原因分析
核心问题出在文件流的读取位置上:
- 调用
json::accept(streamOfFile)时,函数会读取整个文件流内容验证JSON格式,此时文件流的指针已移动到文件末尾。 - 后续调用
json::parse(streamOfFile)时,流中无剩余内容可读取,相当于解析空数据,因此抛出解析异常。
解决方法
方法1:重置文件流指针到开头
在调用parse()前,重置流的读取位置和状态:
// 在accept之后、parse之前添加以下代码 streamOfFile.clear(); // 清除流的错误状态标志 streamOfFile.seekg(0); // 将读取指针移回文件开头 try { json allRoutines = json::parse(streamOfFile); } catch (json::parse_error& error){ cerr << "Parse error at byte: " << error.byte << endl; }
方法2:先将文件内容读取到字符串中
一次性读取全部内容到字符串,用字符串完成验证和解析,避免流指针问题:
int main (){ string pathToFile = "/absolute/path/to/my/exampledata.json"; ifstream streamOfFile(pathToFile); // 读取文件全部内容到字符串 string jsonContent((istreambuf_iterator<char>(streamOfFile)), istreambuf_iterator<char>()); if(!json::accept(jsonContent)){ cout << "JSON NOT VALID!" << endl; } else { cout << "Nothing to complain about!" << endl; } try { json allRoutines = json::parse(jsonContent); } catch (json::parse_error& error){ cerr << "Parse error at byte: " << error.byte << endl; } return 0; }
方法3:重新打开文件
在解析前关闭并重新打开文件,重置流状态:
if(!json::accept(streamOfFile)){ cout << "JSON NOT VALID!" << endl; } else { cout << "Nothing to complain about!" << endl; streamOfFile.close(); streamOfFile.open(pathToFile); // 重新打开文件,指针回到开头 } try { json allRoutines = json::parse(streamOfFile); } catch (json::parse_error& error){ cerr << "Parse error at byte: " << error.byte << endl; }
内容的提问来源于stack exchange,提问作者schande
相关产品推荐
相关产品推荐

