今天和一个客户平台进行联调,其中平台下发的数据文档说明如:
一开始我当成数组来解析,以为是文档写错了(因为有些接口返回值类型跟文档不对应,也没去纠结了,只是看实际返回类型),后来实际返回的真是如上数据类型,不解的是data直接是数组就可以了,为何要变成字符串呢?跟他们确认,小伙就说是json数组。data值是字符串,以为要自己解析了,仔细一看这个data就是一个json类型的string,只要把string转换成json就可以了。
如有文件内容:
main 函数如下:
int main()
{
Json::Value json;
if(readConfig("personList", json))
{
printf("json[data].type = %d\n", json["data"].type());
Json::Value personlist;
std::string data = json["data"].asString();
if(stringToJson(data, personlist))
{
printf("personlist size = %u, personlist = %s\n", personlist.size(), personlist.toStyledString().c_str());
}
}
return 0;
}
能看到先取出data的值:std::string data = json["data"].asString();
然后再把string 转换成 json:stringToJson(data, personlist),最后执行结果为:
为什么数组就可以下发下来,却要转成string下发?有一种可能是平台组好数据后,一次性把数据转换成不带换行符、制表符、空格的string。
如下的函数:
/**
* @brief 格式化joson字符
* @indent 缩进方式: ""为空时不包含换行和空格、"\t"制表tab、" "空格等
* @outStr
* @return
*/
int32_t toStyledString(const Json::Value &json, std::string &indent, std::string &outStr)
{
std::stringstream os;
Json::StreamWriterBuilder builder;
builder["indentation"] = indent;
std::unique_ptr streamWriter(builder.newStreamWriter());
int32_t iRet = streamWriter->write(json, &os);
if(iRet == 0)
{
outStr = os.str();
}
return iRet;
}
格式化后的字符大小比原文件的大小还大,还是不解。。。。
完整代码:
///用到的json库需要自行编译
#include
#include
#include
bool readConfig(const char *file, Json::Value &result);
bool readBuffer(const char *buf, Json::Value &json);
bool stringToJson(std::string &str, Json::Value &outJson);
int32_t toStyledString(const Json::Value &json, std::string &indent, std::string &outStr);
int main()
{
Json::Value json;
if(readConfig("personList", json))
{
printf("json[data].type = %d\n", json["data"].type());
Json::Value personlist;
std::string data = json["data"].asString();
if(stringToJson(data, personlist))
{
printf("personlist size = %u, data.size = %lu, personlist = %s\n", personlist.size(), data.size(), personlist.toStyledString().c_str());
}
}
std::string indent("");
std::string outStr;
toStyledString(json, indent, outStr);
printf("outStr.size = %lu, styledString = %s\n", outStr.size(), outStr.c_str());
return 0;
}
bool readConfig(const char *file, Json::Value &result)
{
Json::CharReaderBuilder readBuilder;
std::unique_ptr reader(readBuilder.newCharReader());
int32_t fileSize = 0;
char *buffer = nullptr;
std::ifstream configFile(file, std::ios::in | std::ios::binary | std::ios::ate);
if(configFile.good())
{
fileSize = configFile.tellg();
buffer = new char[fileSize + 1];
configFile.seekg(0, std::ios::beg);
configFile.read(buffer, fileSize);
configFile.close();
}
std::cout << "file size: " << fileSize << std::endl;
std::string err;
bool iRet = reader->parse(buffer, buffer + fileSize, &result, &err);
if(!iRet)
{
printf("json parse fail, msg = %s\n", err.c_str());
}
if(buffer != nullptr)
{
delete []buffer;
}
return iRet;
}
bool readBuffer(const char *buf, Json::Value &json)
{
if(buf == nullptr)
{
return false;
}
Json::CharReaderBuilder readBuilder;
std::unique_ptr reader(readBuilder.newCharReader());
int32_t len = strlen(buf);
char *buffer = nullptr;
if(len > 0)
{
buffer = new char[len + 1];
memcpy(buffer, buf, strlen(buf));
}
std::string err;
bool iRet = reader->parse(buffer, buffer + len, &json, &err);
if(!iRet)
{
printf("json parse fail, msg = %s\n", err.c_str());
}
if(buffer != nullptr)
{
delete []buffer;
}
return iRet;
}
bool stringToJson(std::string &str, Json::Value &outJson)
{
return readBuffer(str.c_str(), outJson);
}
/**
* @brief 格式化joson字符
* @indent 缩进方式: ""为空时不包含换行和空格、"\t"制表tab、" "空格等
* @outStr
* @return
*/
int32_t toStyledString(const Json::Value &json, std::string &indent, std::string &outStr)
{
std::stringstream os;
Json::StreamWriterBuilder builder;
builder["indentation"] = indent;
std::unique_ptr streamWriter(builder.newStreamWriter());
int32_t iRet = streamWriter->write(json, &os);
if(iRet == 0)
{
outStr = os.str();
}
return iRet;
}