RapidJSON是腾讯开源的一个高效的C++ JSON解析器及生成器,它是只有头文件的C++库。RapidJSON是跨平台的,支持Windows, Linux, Mac OS X及iOS, Android。它的源码在https://github.com/Tencent/rapidjson/,稳定版本为2016年发布的1.1.0版本。官方教程:http://rapidjson.org/zh-cn/md_doc_tutorial_8zh-cn.html
RapidJSON特点:
(1). RapidJSON小而全:它同时支持SAX和DOM风格的API,SAX解析器只有约500行代码。
(2). RapidJSON快:它的性能可与strlen()相比,可支持SSE2/SSE4.2加速,使用模版及内联函数去降低函数调用开销。
(3). RapidJSON独立:它不依赖于BOOST等外部库,它甚至不依赖于STL。
(4). RapidJSON对内存友好:在大部分32/64位机器上,每个JSON值只占16字节(除字符串外),它预设使用一个快速的内存分配器,令分析器可以紧凑地分配内存。
(5). RapidJSON对Unicode友好:它支持UTF-8、UTF-16、UTF-32(大端序/小端序),并内部支持这些编码的检测、校验及转码。例如,RapidJSON可以在分析一个UTF-8文件至DOM (Document Object Model, 文件对象模型)时,把当中的JSON字符串转码至UTF-16。它也支持代理对(surrogate pair)及"\u0000"(空字符)。
每个JSON值都储存为Value类,而Document类则表示整个DOM,它存储了一个DOM 树的根Value。RapidJSON的所有公开类型及函数都在rapidjson命名空间中。
以上内容摘自:http://rapidjson.org/zh-cn/,关于RapidJSON的更详细介绍可以参考此网页。
1. rapidjson解析
test.json文件
[
{
"name":"Jon",
"sex":"male",
"info":["This is A","This is B"]
},
{
"name":"alli",
"sex":"female",
"info":["This is C","This is D"]
}
]
解析函数:
/**
* @func: GetCurrentTimeMillisecond
* @brief: 解析.json文件内容,将数据加载到内存中
* @author: xxx 2020.5.11
* @param: 无
* @return: 执行结果
*/
int XXX::loadJson()
{
std::ifstream fin("./setting/test.json", std::ios::binary);
if (!fin)
{
return -1;
}
//读取文件内容
std::vector<char> buf(fin.seekg(0, std::ios::end).tellg());
fin.seekg(0, std::ios::beg).read(&buf[0], static_cast<std::streamsize>(buf.size()));
fin.close();
rapidjson::Document doc;
char* m_buf = new char[buf.size() + 1];
copy(buf.begin(), buf.end(), m_buf);
m_buf[buf.size()] = 0;
if (doc.ParseInsitu(m_buf).HasParseError())
{
delete[] m_buf;
return false;
}
for (rapidjson::Value::ConstValueIterator itr = doc.Begin(); itr != doc.End(); ++itr)
{
const char* szName = (*itr)["name"].GetString();
const char* szSex = (*itr)["sex"].GetString();
const rapidjson::Value& a = (*itr)["info"];
std::vector<std::string> v;
for (rapidjson::Value::ConstValueIterator itr1 = a.Begin(); itr1 != a.End(); ++itr1)
{
v.push_back((*itr1).GetString());
}
}
return 0;
}
注意如果你要想修改json数据,name在遍历的时候记得用rapidjson::Value::ValueIterator,不然你无法改变json数据,原因是迭代器是不是const的,是const的就不能改变数据。
2.修改json数据
[
{
"name1": "小明",
"type": 1,
"secondType": 3,
"info": [
{
"school": "cpu",
"address": "ct.road.107",
}
],
"backupInfo": [
{
"phone": "123456",
"email": "123456@163.com",
}
]
},
{
"name": "小芳",
"type": 1,
"secondType": 3,
"info": [
{
"school": "njuu",
"address": "hf.road.108",
}
],
"backupInfo": [
{
"phone": "1234567",
"email": "1234567@qq.com",
}
]
}
]
QString szChangeItemInfo = pCompareItem->data(COLUMN_IED_NAME, IED_ROLE).toString();
rapidjson::Document doc(rapidjson::kObjectType);
rapidjson::Document::AllocatorType& allocator = doc.GetAllocator();
char szItemText[10000] = "";
if (szChangeItemInfo.at(0) != '{')
{
szChangeItemInfo.insert(0, '{');
szChangeItemInfo += "]}";
}
strcpy(szItemText, QStrToStr(szChangeItemInfo));
//szItemText:一级array里元素
if (!doc.ParseInsitu(szItemText).HasParseError())
{
if (doc.IsObject())
{
rapidjson::Value& type_item = doc["type"];
rapidjson::Value& secondType_item = doc["secondType"];
std::string szType = szNewType.toUtf8().data();
type_item.SetInt(atoi(szType.c_str()));
phaseType_item.SetInt(szNewPhaseType.toInt());
}
//将json数据转化为 QString 存到item
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
doc.Accept(writer);
char szBreak[50000];
strcpy(szBreak, buffer.GetString());
szChangeItemInfo = StrToQStr(szBreak);
pCompareItem->setData(COLUMN_IED_NAME, IED_ROLE, szChangeItemInfo);
}
3.组建json
rapidjson::Document doc;
rapidjson::Document::AllocatorType& allocator = doc.GetAllocator();
rapidjson::Value v(rapidjson::kObjectType);
rapidjson::Value logRecord(rapidjson::kArrayType);
for (int i = 0; i < vec.size(); i++)
{
rapidjson::Value logFile(rapidjson::kObjectType);
logFile.AddMember("num", vec[i].num, allocator);
logFile.AddMember("fileTime", rapidjson::StringRef(vec[i].fileTime.c_str()), allocator);
logFile.AddMember("fileName", rapidjson::StringRef(vec[i].fileName.c_str()), allocator);
logFile.AddMember("filePath", rapidjson::StringRef(vec[i].filePath.c_str()), allocator);
logRecord.PushBack(logFile, allocator);
}
v.AddMember("files", logRecord, allocator);
v.AddMember("count", nCount, allocator);
v.AddMember("index", nIndex > 0 ? nIndex : 1, allocator);
restful_response(v, nc);