当前位置:   article > 正文

jsoncpp使用小结_jsoncpp用法

jsoncpp用法

一、jsoncpp介绍

        jsoncpp是一个开源C++库,提供对JSON字符串序列化/反序列化的功能。

开源地址:GitHub - open-source-parsers/jsoncpp: A C++ library for interacting with JSON.

文档地址:http://open-source-parsers.github.io/jsoncpp-docs/doxygen/index.html
 

二、jsoncpp的使用

        jsoncpp主要包含三种类型的C++类 - value、reader、writer。value表示json对象和数组。reader用于反序列化json字符串。writer用于序列化json字符串。简单使用示例:

示例1:生成json

  1. Json::Value jsonRoot; //定义根节点
  2. Json::Value jsonItem; //定义一个子对象
  3. jsonItem["item1"] = "one"; //添加数据
  4. jsonItem["item2"] = 2;
  5. jsonRoot.append(jsonItem);
  6. jsonItem.clear(); //清除jsonItemjsonItem["item1.0"] = 1.0;
  7. jsonItem["item2.0"] = 2.0;
  8. jsonRoot["item"] = jsonItem;
  9. std::string strJson = jsonRoot.toStyledString(); //json结果

示例2:读取json

  1. Json::Reader reader;
  2. string json_document = "{\"age\" : 123, \"name\" : \"weng\"}";
  3. if (!reader.parse(json_document, json_object))
  4. {
  5.      cout << "error" << endl;
  6.      return 0;
  7.  }
  8. else
  9. {
  10.    cout <<"age:" <<json_object["age"] << " name" << json_object["name"] << endl;
  11. }

示例3:空数组

  1. Json::Value root;  
  2. root["FaceItemObjects"].resize(0);  
  3. std::string strJson = root.toStyledString();

序列化复杂json字符串

  1. //写json对象数组
  2. Json::Value root;
  3. Json::Value itemFaceArray;
  4. Json::value itemFace;
  5. root["errorCode"] = 0;
  6. root["faces"].resize(0);
  7. //face1
  8. itemFace["x"]=1;
  9. itemFace["y"]=1;
  10. itemFace["width"]=100;
  11. itemFace["height"]=100;
  12. itemFace["score"]=95;
  13. itemFaceArray.append(itemFace);
  14. //face2
  15. itemFace.clear();
  16. itemFace["x"]=200;
  17. itemFace["y"]=200;
  18. itemFace["width"]=100;
  19. itemFace["height"]=100;
  20. itemFace["score"]=98;
  21. itemFaceArray.append(itemFace);
  22. root["faces"= itemFaceArray;
  23. std::string strJson = root.toStyledString();
  24. //读json对象数组
  25. Json::value itemFace;
  26. int nFaceCount = root["faces"].size();
  27. int n = 0;
  28. for(n=0; n<nFaceCount; n++)
  29. {
  30. itemFace = root["faces"][n];
  31. int nScore = itemFace["score"].asInt();
  32. }

示例5:从文件中读取JSON。

  1. #include <string>
  2. #include <json/json.h>
  3. #include <iostream>
  4. #include <fstream>
  5. //从文件中读取JSON
  6. void readFileJson()
  7. {
  8. Json::Reader reader;
  9. Json::Value root;
  10. //从文件中读取,保证当前文件有test.json文件
  11. ifstream in("test.json", ios::binary);
  12. if( !in.is_open() )
  13. {
  14. cout << "Error opening file\n";
  15. return;
  16. }
  17. if(reader.parse(in,root))
  18. {
  19. //读取根节点信息
  20. string name = root["name"].asString();
  21. int age = root["age"].asInt();
  22. }
  23. else
  24. {
  25. cout << "parse error\n" << endl;
  26. }
  27. in.close();
  28. }

示例6:写JSON至文件中。

  1. //写JSON至文件中
  2. void writeFileJson()
  3. {
  4. //根节点
  5. Json::Value root;
  6. //根节点属性
  7. root["name"] = Json::Value("Mike");
  8. root["age"] = Json::Value(21);
  9. //输出到文件
  10. ofstream os;
  11. os.open("test.json");
  12. os << sw.write(root);
  13. os.close();
  14. }

三、注意事项

1、jsoncpp不支持int64位的。

解决方法1:需要0.6.0rc2版本。 不要采用0.5.0版本,因为它没有64位int。

解决方法2:0.5.0版本基础上修改代码支持64位int。具体参考json-cpp / Discussion / Open Discussion: Support for int64/uint64 numbers

解决方法3:asUInt换成asDouble
 

  1. Json::Reader reader;
  2. Json::Value root;
  3. if (reader.parse(str, root))
  4. {
  5. //获取里面内容
  6. OutputDebugString(_T("STRING TO JSON \n"));
  7. //std::string str1 = root["messageType"].asString();
  8. long long tmstamp = ((long long)(root["sendTime"].asUInt()))/1000;
  9. WCHAR* wstr = NULL;
  10. TimestampToLocalTime(&wstr,tmstamp);
  11. }

结果发现第8行会出错,查了下错误原因, 原来SendTime是一个一毫秒为单位的时间戳,其值为1403575350411,这个值的大小远远超出了 unsigned int 或者 int的最大值,只能用INT64来表示, 但是看看Json::Value里面的函数只有asInt, asUint,没有取64位整数的函数,那怎么办呢?里面虽然没有64位的但是有一个asDouble,duoble的指数为11位,能表示的范围比Int64还大,所以上面的asUInt换成asDouble就可以了。

解决方法4:使用高版本(比如1.8.4),在使用jsoncpp库的工程属性预定义中增加JSON_HAS_INT64

2、获取json中不存在名称的值,并且作为asCString()拷贝时,程序会core。如strncpy(a, root["test"].asCString(), sizeof(a));

3、解决jsoncpp中文输出为unicode格式的"\u"、VS读取utf8格式中文输出乱码问题。jsoncpp写文件中文,不进行streamWritebuilder的设置,写入的中文会变成unicode形式(比如:\u0375 \u0376)。
高版本jsoncpp(比如:1.8.4)不需要修改代码。。低版本jsoncp,需要修改改代码参考:c++ jsoncpp使用toStyledString生成字符串中文乱码解决方案_tostylestring_wgxh05的博客-CSDN博客

4、jsoncpp中文输出不带\u格式(\u表示unicode编码;不带\u就是使用utf-8编码),使用streamWritebuilder。

  1. //写文件
  2. #include <codecvt>
  3. #include<windows.h>
  4. #include<iostream>
  5. #include<string>
  6. #include<json/json.h>
  7. #include<fstream>
  8. Json::Value root;
  9. //中文转换成utf-8
  10. std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> convert;
  11. std::string utf8_string = convert.to_bytes(L"王五");
  12. root["name"] = utf8_string;
  13. root["age"] = 20;
  14. //关键在于对builder的属性设置
  15. Json::StreamWriterBuilder builder;
  16. static Json::Value def = []() {
  17. Json::Value def;
  18. Json::StreamWriterBuilder::setDefaults(&def);
  19. def["emitUTF8"] = true;
  20. return def;
  21. }();
  22. builder.settings_ = def;//Config emitUTF8
  23. const std::unique_ptr<Json::StreamWriter> writer(builder.newStreamWriter());
  24. std::fstream fs;
  25. fs.open("save.json", std::ios::out);
  26. writer->write(root, &fs);
  27. fs.close();
  1. //写utf-8返回字符串
  2. std::string JsonToString(const Json::Value & root)
  3. {
  4. static Json::Value def = []() {
  5. Json::Value def;
  6. Json::StreamWriterBuilder::setDefaults(&def);
  7. def["emitUTF8"] = true;
  8. return def;
  9. }();
  10. std::ostringstream stream;
  11. Json::StreamWriterBuilder stream_builder;
  12. stream_builder.settings_ = def;//Config emitUTF8
  13. std::unique_ptr<Json::StreamWriter> writer(stream_builder.newStreamWriter());
  14. writer->write(root, &stream);
  15. return stream.str();
  16. }

  1. //读文件
  2. #include <codecvt>
  3. #include<windows.h>
  4. #include<iostream>
  5. #include<string>
  6. #include<json/json.h>
  7. #include<fstream>
  8. //读入文件时将文件编码设置为UTF-8
  9. std::ifstream ifs("file.json", std::ios::in | std::ios::binary);
  10. ifs.imbue(std::locale(std::locale(), new std::codecvt_utf8<wchar_t>));
  11. Json::Reader reader;
  12. Json::Value root;
  13. if(reader.parse(ifs,root))
  14. {
  15. //读取根节点信息
  16. string name = root["name"].asString();
  17. int age = root["age"].asInt();
  18. }
  19. else
  20. {
  21. cout << "parse error\n" << endl;
  22. }
  23. ifs.close();

5、fatal error C1083: 无法打开编译器生成的文件:“../../build/vs71/release/lib_json\json_value.asm”: No such file or directory 

解决方法:修改生成静态库文件的工程的属性:路径为:菜单---项目--属性---配置属性---c/c++---输出文件---汇编程序输出:无列表

6、异常捕获

  1. bool bReadJsonSuccess = false;
  2. try
  3. {
  4. Json::Reader reader;
  5. string json_document = "{\"age\" : 123, \"name\" : \"weng\"}";
  6. if (!reader.parse(json_document, json_object))
  7. {
  8. cout << "error" << endl;
  9. bReadJsonSuccess = false;
  10. }
  11. else
  12. {
  13. cout <<"age:" <<json_object["age"] << " name" << json_object["name"] << endl;
  14. bReadJsonSuccess = true;
  15. }
  16. }
  17. catch(...)
  18. {
  19. bReadJsonSuccess = false;
  20. }

7、json字符串的格式化及非格式化转换。

转为格式化字符串,里面加了很多空格及换行符
string strJson1 = root.toStyledString();

转为未格式化字符串,无多余空格及换行符
Json::FastWriter writer;
string strJson1 = writer.write(root);

8、遍历Json::Value

1)利用getMemberNames方法获取Json::Value的键列表,本质是字符串向量。
typedef std::vector<std::string> Json::Value::Members;
2)再根据 key 值寻找Value,然后递归调用。

  1. void objectValue(Json::Value &value)
  2. {
  3. Json::Value::Members mem = value.getMemberNames();
  4. for (auto iter = mem.begin(); iter != mem.end(); iter++) {
  5. printf("%s : ", (*iter).c_str()); // 打印键名
  6. typeSwitch(value[*iter]);
  7. }
  8. }
  9. void typeSwitch(Json::Value &value)
  10. {
  11. switch (value.type())
  12. {
  13. case Json::objectValue :
  14. objectValue(value);
  15. break;
  16. case Json::arrayValue :
  17. {
  18. auto count = value.size();
  19. for (unsigned int i = 0; i < count; i++)
  20. typeSwitch(value[i]);
  21. }
  22. break;
  23. case Json::stringValue :
  24. printf("%s\n", value.asString().c_str());
  25. break;
  26. case Json::realValue :
  27. printf("%lf\n", value.asDouble());
  28. break;
  29. case Json::uintValue :
  30. printf("%u\n", value.asUInt());
  31. break;
  32. case Json::intValue :
  33. printf("%d\n", value.asInt());
  34. break;
  35. case Json::booleanValue :
  36. printf("%d\n", value.asBool());
  37. break;
  38. default :
  39. break;
  40. }
  41. }

9、jsoncpp 中关于浮点数的控制问题。

解决方法1:浮点数使用字符串替换。

解决方法2:使用precision控制精度。比如:

writerBuilder.settings_[“precision”] = 16;
该选项表示浮点数能存储的位数的最大个数,包括整数位,默认是17

  1. #incllude <string>
  2. #include <iostream>
  3. using namespace std;
  4. int main(int argc, const char *argv[])
  5. {
  6. Json::Value rootInput;
  7. Json::CharReaderBuilder readerBuilder;
  8. char szInputContent[256] = {0};
  9. sprintf(szInputContent, "%s", "{\"name\":\"john\",\"age\":3.15}");
  10. unique_ptr<Json::CharReader> const jsonReader(readerBuilder.newCharReader());
  11. if(!rjsonReader->parse(szInputContent, &rootInput)) {
  12. cout << "parseJson err. " << endl;
  13. return -1;
  14. }
  15. string name = rootInput["name"].asString();
  16. double age = rootInput["age"].asDouble();
  17. cout << "name:"<<name << " age:" <<age << endl;
  18. string jsonStr;
  19. Json::Value root;
  20. Json::StreamWriterBuilder writerBuilder;
  21. std::ostringstream os;
  22. int c = 4;
  23. string str_get;
  24. double get = precision(age, c, str_get);
  25. root["Name"] = name;
  26. root["Age"] = get;
  27. writerBuilder.settings_["precision"] = 16;
  28. //writerBuilder.settings_["emitUTF8"] = true;
  29. std::unique_ptr<Json::StreamWriter> jsonWriter(writerBuilder.newStreamWriter());
  30. jsonWriter->write(root, &os);
  31. jsonStr = os.str();
  32. cout << (char *)jsonStr.c_str() << endl;
  33. return 0;
  34. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/595721
推荐阅读
相关标签
  

闽ICP备14008679号