RapidJSON 是只有头文件的 C++ 库。只需把 include/rapidjson
目录复制至系统或项目的 include 目录中。
速成参考:http://www.bubuko.com/infodetail-2961998.html
void OnBnClickedCmdSave()
{
rapidjson::StringBuffer strBuf;
//rapidjson::Writer<rapidjson::StringBuffer> writer(strBuf);
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(strBuf);//PrettyWriter带\n换行符
writer.StartObject();
#if 0
//1. 整数类型
writer.Key("Int");
writer.Int(1);
//2. 浮点类型
writer.Key("Double");
writer.Double(12.0000001);
//3. 字符串类型
writer.Key("String");
writer.String("This is a string");
//4. 结构体类型
writer.Key("Object");
writer.StartObject();
writer.Key("name");
writer.String("qq849635649");
writer.Key("age");
writer.Int(25);
writer.EndObject();
//5. 数组类型
//5.1 整型数组
writer.Key("IntArray");
writer.StartArray();
//顺序写入即可
writer.Int(10);
writer.Int(20);
writer.Int(30);
writer.EndArray();
//5.2 浮点型数组
writer.Key("DoubleArray");
writer.StartArray();
for(int i = 1; i < 4; i++)
{
writer.Double(i * 1.0);
}
writer.EndArray();
//5.3 字符串数组
writer.Key("StringArray");
writer.StartArray();
writer.String("one");
writer.String("two");
writer.String("three");
writer.EndArray();
//5.4 混合型数组
//这说明了,一个json数组内容是不限制类型的
writer.Key("MixedArray");
writer.StartArray();
writer.String("one");
writer.Int(50);
writer.Bool(false);
writer.Double(12.005);
writer.EndArray();
#endif
//5.5 结构体数组
writer.Key("Commands");
writer.StartArray();
HTREEITEM root = m_DeviceTree.GetRootItem();
HTREEITEM hCurCategoryItem = m_DeviceTree.GetChildItem(root);
while(hCurCategoryItem)
{
HTREEITEM hTempCategoryItem = hCurCategoryItem;
hCurCategoryItem = m_DeviceTree.GetNextSiblingItem(hCurCategoryItem);
//
HTREEITEM hCurCmdItem = m_DeviceTree.GetChildItem(hTempCategoryItem);
while(hCurCmdItem){
HTREEITEM hTempCmdItem = hCurCmdItem;
hCurCmdItem = m_DeviceTree.GetNextSiblingItem(hCurCmdItem);
//
NODE_INFO* pNode = (NODE_INFO*)m_DeviceTree.GetItemData(hTempCmdItem);
writer.StartObject();
writer.Key("uuid");
writer.String(pNode->operationCmdInfo->cmdGUID?pNode->operationCmdInfo->cmdGUID: "");
writer.Key("alias");
writer.String(pNode->operationCmdInfo->cmdDesc?pNode->operationCmdInfo->cmdDesc: "");
writer.Key("categoryCode");
writer.String(pNode->categoryCode?pNode->categoryCode: "");
writer.Key("categoryName");
writer.String(pNode->categoryName?pNode->categoryName: "");
writer.Key("model");
writer.String(pNode->operationCmdInfo->deviceModel? pNode->operationCmdInfo->deviceModel: "");
writer.Key("brand");
writer.String(pNode->operationCmdInfo->deviceBrand?pNode->operationCmdInfo->deviceBrand:"");
writer.Key("timeout");
writer.Int(pNode->operationCmdInfo->ackRecvOverTimeSec);
writer.Key("protocol");
writer.String((pNode->operationCmdInfo->protocol == CDeviceMapTree::cmd_interface_modbus_tcp)?"modbus":"raw");
//
writer.Key("connectType");
writer.String("tcp");
writer.Key("connectParam");
char tmp[512];
sprintf_s(tmp, "%s:%d", pNode->operationCmdInfo->defaultTcpParam.IpAddr,pNode->operationCmdInfo->defaultTcpParam.IpPort);
writer.String(tmp);
//
if(pNode->operationCmdInfo->protocol== CDeviceMapTree::cmd_interface_modbus_tcp)
{
writer.Key("modbusCommand");
MODBUS_PROTOCOL_INFO* pModbusCmdInfo = &(pNode->operationCmdInfo->modbusCmdInfo);
writer.StartObject();
writer.Key("slaveAddr"); writer.Int(pModbusCmdInfo->slaveAddr);
writer.Key("opCode"); writer.Int(pModbusCmdInfo->opCode);
writer.Key("regAddrStart"); writer.Int(pModbusCmdInfo->regAddrStart);
writer.Key("regNumbers"); writer.Int(pModbusCmdInfo->regNumbers);
writer.Key("regValue"); writer.Int(pModbusCmdInfo->regValue);
writer.Key("regValueString"); writer.String(pModbusCmdInfo->szHexVals?pModbusCmdInfo->szHexVals:"");
//writer.Key("X"); writer.String(NULL); //NULL导致异常
writer.EndObject();
}
//
else
{
RAW_CMD_INFO * pRawCmdInfo = &(pNode->operationCmdInfo->rawCmdInfo); //tcp-raw uart-raw gateway-raw有效
writer.Key("rawCommand");
writer.StartObject();
writer.Key("cmd"); writer.String(pRawCmdInfo->szCmdHexData?pRawCmdInfo->szCmdHexData:"");
writer.Key("ackTemplate"); writer.String(pRawCmdInfo->szAckHexDataTemplate?pRawCmdInfo->szAckHexDataTemplate: "");
writer.Key("ackMask"); writer.String(pRawCmdInfo->szAckHexDataMask?pRawCmdInfo->szAckHexDataMask: "");
writer.Key("ackLenExpected"); writer.Int(pRawCmdInfo->ackLenExpected);
writer.EndObject();
}
writer.EndObject();
}
}
writer.EndArray();
//
#if 0
writer.Key("UartCommands");
writer.StartArray();
for(int i = 0; i < 3; i++)
{
writer.StartObject();
writer.Key("name");
writer.String("qq849635649");
writer.Key("age");
writer.Int(i * 10);
writer.Key("sex");
writer.Bool((i % 2) == 0);
writer.EndObject();
}
writer.EndArray();
#endif
//
#if 0
writer.Key("GatewayCommands");
writer.StartArray();
for(int i = 0; i < 3; i++)
{
writer.StartObject();
writer.Key("name");
writer.String("qq849635649");
writer.Key("age");
writer.Int(i * 10);
writer.Key("sex");
writer.Bool((i % 2) == 0);
writer.EndObject();
}
writer.EndArray();
#endif
//
writer.EndObject();
std::string data = strBuf.GetString();
{
//rapidjson::Document doc;
//char* tmp = _strdup(data.c_str());
//int len = strlen(tmp);
// if (doc.ParseInsitu(tmp).HasParseError()){
// NetPrintf("%s", "配置文件解析失败!");
// }
}
NetPrintf("%s", data.c_str());
FILE* f ;
fopen_s(&f, "TcpCommands.conf", "w");
if(f)
{
fwrite( data.c_str(), 1, data.length()+1, f);
fclose(f);
}
}
==========================================================================
》》》解析参考
void LoadFromConfFile(const char* filename, const char* connectType)
{
FILE* f;
char* buf = NULL;
fopen_s(&f, filename, "r");
do{
if(!f) break;
fseek(f, 0, SEEK_END);
long fileLen = ftell(f);
fseek(f, 0, SEEK_SET);
buf = new char[fileLen+1];
int n = fread(buf, 1, fileLen, f);
if(f) fclose(f);
buf[n] = '\0';
TRACE("%s\n", buf);
//解析json配置文件数据
try{
rapidjson::Document doc;
if (doc.ParseInsitu(buf).HasParseError()){
NetPrintf("%s", "配置文件解析失败!");
break;
}
if (!doc.HasMember("Commands")) break;
rapidjson::Value &commands = doc["Commands"];
if(!commands.IsArray()) break;
if(commands.Empty()) break;
rapidjson::Value command;
NODE_INFO* pNode= NULL;
for (rapidjson::SizeType i = 0; i < commands.Size(); i++)
{
command = commands[i]; //Array中每个元素又是一个Object
//
if(!command.HasMember("connectType")) continue;
if(!command.HasMember("protocol")) continue;
char* curConnectType = _strdup(command["connectType"].GetString());
if(0 != _stricmp(curConnectType, connectType)) {
free(curConnectType);
break;
}
free(curConnectType);
pNode= new NODE_INFO;
pNode->nodeType = enum_node_cmd;
pNode->bModifyEnabled = TRUE;
pNode->hTreeItem = NULL;
pNode->categoryCode = command.HasMember("categoryCode")?_strdup(command["categoryCode"].GetString()) :_strdup("");
pNode->categoryName = command.HasMember("categoryName")?_strdup(command["categoryName"].GetString()) :_strdup("");
//查找节点所在的树节点-- 没找到则创建
HTREEITEM root = this->GetRootItem();
ASSERT(root);
HTREEITEM hCurCategoryItem = GetChildItem(root);
while(hCurCategoryItem)
{
CString strCategoryName = GetItemText(hCurCategoryItem);
USES_CONVERSION;
int n = strCategoryName.Find(A2T(pNode->categoryCode));
if(n != -1)
break;
hCurCategoryItem = GetNextSiblingItem(hCurCategoryItem);
}
if(!hCurCategoryItem){
char temp[128];
sprintf_s(temp, sizeof(temp),"%s%s", pNode->categoryCode, pNode->categoryName );
USES_CONVERSION;
hCurCategoryItem = InsertItem(A2T(temp), root);
SetItemDataExt(hCurCategoryItem, pNode->categoryCode, pNode->categoryName);
NODE_INFO *categoryNode = new NODE_INFO;
categoryNode->nodeType = enum_node_category;
categoryNode->bModifyEnabled = FALSE;
categoryNode->hTreeItem = hCurCategoryItem;
categoryNode->categoryCode = _strdup(pNode->categoryCode);
categoryNode->categoryName = _strdup(pNode->categoryName);
SetItemData(hCurCategoryItem, (DWORD_PTR)categoryNode);
}
OPERATION_CMD_INFO* pOperationCmdInfo = new OPERATION_CMD_INFO;
ASSERT(pOperationCmdInfo);
pNode->operationCmdInfo = pOperationCmdInfo;
pOperationCmdInfo->cmdDesc = command.HasMember("alias")?_strdup(command["alias"].GetString()) :_strdup("");
pOperationCmdInfo->cmdGUID = command.HasMember("uuid")?_strdup(command["uuid"].GetString()) :_strdup("");
pOperationCmdInfo->deviceBrand = command.HasMember("brand")?_strdup(command["brand"].GetString()) :_strdup("");
pOperationCmdInfo->deviceModel = command.HasMember("model")?_strdup(command["model"].GetString()) :_strdup("");
pOperationCmdInfo->ackRecvOverTimeSec = command["timeout"].GetInt();
USES_CONVERSION;
pNode->hTreeItem = InsertItem(A2T(pOperationCmdInfo->cmdDesc), hCurCategoryItem);
SetItemData(pNode->hTreeItem, (DWORD_PTR)pNode);
char* protocol = _strdup(command["protocol"].GetString());
if(0 == _stricmp(connectType, "tcp"))
{
pOperationCmdInfo->protocol = (0 == _stricmp(protocol, "modbus"))? CDeviceMapTree::cmd_interface_modbus_tcp : CDeviceMapTree::cmd_interface_raw_tcp;
char* tcpConnectParam = command.HasMember("connectParam") ? _strdup(command["connectParam"].GetString()) : _strdup("192.168.0.140:502");
char* ip = tcpConnectParam;
char* p = ip;
while (p&& *p != ':') p++;
if (*p == ':'){
*p++ = '\0';
pOperationCmdInfo->defaultTcpParam.IpAddr = _strdup(ip);
pOperationCmdInfo->defaultTcpParam.IpPort = atoi(p);
}
else{
pOperationCmdInfo->defaultTcpParam.IpAddr = _strdup(ip);
pOperationCmdInfo->defaultTcpParam.IpPort = 502;//default tcp-modbus port
}
free(tcpConnectParam);
}
else if(0 == _stricmp(connectType, "uart"))
{
pOperationCmdInfo->protocol = (0 == _stricmp(protocol, "modbus"))? CDeviceMapTree::cmd_interface_modbus_uart : CDeviceMapTree::cmd_interface_raw_uart;
char* uartConnectParam = command.HasMember("connectParam") ? _strdup(command["connectParam"].GetString()) : _strdup("COM4:9600,8,N,1");
char* commfile = uartConnectParam;
char* p = commfile;
while (p&& *p != ':') p++;
if (*p == ':'){
*p++ = '\0';
pOperationCmdInfo->defaultyUartParam.uartPort = atoi(&commfile[3]) - 1; //commfile=COM5跳过字符COM
pOperationCmdInfo->defaultyUartParam.conn_param = _strdup(p);
}
else{
pOperationCmdInfo->defaultyUartParam.uartPort = 4;
pOperationCmdInfo->defaultyUartParam.conn_param = _strdup("9600,8,N,1");
}
free(uartConnectParam);
}
else if(0 == _stricmp(connectType, "gateway"))
{
pOperationCmdInfo->protocol = (0 == _stricmp(protocol, "gw_WR"))? CDeviceMapTree::cmd_interface_gateway_wr :
(0 == _stricmp(protocol, "gw_W"))? CDeviceMapTree::cmd_interface_gateway_w:
CDeviceMapTree::cmd_interface_gateway_r ;
char* tcpConnectParam = command.HasMember("connectParam") ? _strdup(command["connectParam"].GetString()) : _strdup("192.168.0.140:502");
char* ip = tcpConnectParam;
char* p = ip;
while (p&& *p != ':') p++;
if (*p == ':'){
*p++ = '\0';
pOperationCmdInfo->defaultTcpParam.IpAddr = _strdup(ip);
pOperationCmdInfo->defaultTcpParam.IpPort = atoi(p);
}
else{
pOperationCmdInfo->defaultTcpParam.IpAddr = _strdup(ip);
pOperationCmdInfo->defaultTcpParam.IpPort = 502;//default tcp-modbus port
}
free(tcpConnectParam);
//提取gateway命令参数
if(command.HasMember("gatewayCommand"))
{
rapidjson::Value &gatewayCommand = command["gatewayCommand"];
pOperationCmdInfo->gatewayCmdInfo.incomingDataLenExpected = gatewayCommand.HasMember("IncomingDataLen")?gatewayCommand["IncomingDataLen"].GetInt(): 65535;
pOperationCmdInfo->gatewayCmdInfo.szHexPassThrouhVals = gatewayCommand.HasMember("PassthroughDataHex")?_strdup(gatewayCommand["PassthroughDataHex"].GetString()): _strdup("");
if(gatewayCommand.HasMember("UartParam"))
{
rapidjson::Value &UartParam = gatewayCommand["UartParam"];
pOperationCmdInfo->gatewayCmdInfo.uartParam.uartPort = UartParam.HasMember("UartPort")?UartParam["UartPort"].GetInt(): 0;
pOperationCmdInfo->gatewayCmdInfo.uartParam.conn_param = UartParam.HasMember("ConnParam")?_strdup(UartParam["ConnParam"].GetString()): _strdup("9600,8,N,1");
}
}
}
else
{
free(protocol);
delete pNode;
pNode = NULL;
continue;
}
free(protocol);
switch(pOperationCmdInfo->protocol)
{
case CDeviceMapTree::cmd_interface_modbus_tcp:
case CDeviceMapTree::cmd_interface_modbus_uart:
if (command.HasMember("modbusCommand"))
{//modbus初始参数
MODBUS_PROTOCOL_INFO* pModbusCmdInfo = &(pOperationCmdInfo->modbusCmdInfo);
rapidjson::Value &modbusCmdInfo = command["modbusCommand"];
pModbusCmdInfo->slaveAddr = modbusCmdInfo.HasMember("slaveAddr") ? modbusCmdInfo["slaveAddr"].GetInt() : 0xFF;
pModbusCmdInfo->opCode = modbusCmdInfo.HasMember("opCode") ? modbusCmdInfo["opCode"].GetInt() : 0x01;
pModbusCmdInfo->regAddrStart = modbusCmdInfo.HasMember("regAddrStart") ? modbusCmdInfo["regAddrStart"].GetInt() : 0xFFFF;
pModbusCmdInfo->regNumbers = modbusCmdInfo.HasMember("regNumbers") ? modbusCmdInfo["regNumbers"].GetInt() : 1;
pModbusCmdInfo->regValue = modbusCmdInfo.HasMember("regValue") ? modbusCmdInfo["regValue"].GetInt() : 0x1234;
pModbusCmdInfo->szHexVals = modbusCmdInfo.HasMember("regValueString") ? _strdup(modbusCmdInfo["regValueString"].GetString()) : _strdup("");
}
break;
case CDeviceMapTree::cmd_interface_raw_tcp:
case CDeviceMapTree::cmd_interface_raw_uart:
case CDeviceMapTree::cmd_interface_gateway_wr :
case CDeviceMapTree::cmd_interface_gateway_w :
case CDeviceMapTree::cmd_interface_gateway_r :
if (command.HasMember("rawCommand"))
{
RAW_CMD_INFO * pRawCmdInfo = &(pNode->operationCmdInfo->rawCmdInfo); //tcp-raw uart-raw gateway-raw有效
rapidjson::Value &rawCmdInfo = command["rawCommand"];
pRawCmdInfo->szCmdHexData = rawCmdInfo.HasMember("cmd") ? _strdup(rawCmdInfo["cmd"].GetString()) : _strdup("");
pRawCmdInfo->szAckHexDataTemplate = rawCmdInfo.HasMember("ackTemplate") ? _strdup(rawCmdInfo["ackTemplate"].GetString()) : _strdup("");
pRawCmdInfo->szAckHexDataMask = rawCmdInfo.HasMember("ackMask") ? _strdup(rawCmdInfo["ackMask"].GetString()) : _strdup("");
pRawCmdInfo->ackLenExpected = rawCmdInfo.HasMember("ackLenExpected") ? rawCmdInfo["ackLenExpected"].GetInt() : 0;
}
break;
}
}//end for
}
catch(...){
NetPrintf("%s", "配置文件解析异常!");
}
}while(0);
if(buf) delete buf;
if(f) fclose(f);
}