C++ 解析Json——jsoncpp

本文介绍Jsoncpp库的两种使用方式:一是直接引入lib文件,二是包含源代码文件,并提供了详细的代码示例,演示如何解析和生成JSON数据。
Jsoncpp是个跨平台的开源库,下载地址: http://sourceforge.net/projects/jsoncpp/ ,我下载的是v0.5.0,压缩包大约104K。

方法一:使用Jsoncpp生成的lib文件
       解压上面下载的 Jsoncpp 文件,在jsoncpp-src-0.5.0/makefiles/vs71目录里找到jsoncpp.sln,用VS2008版本编译,默认生成静态链接库。 在工程中引用,只需要包含include/json下的头文件及生成的.lib文件即可。
       如何包含lib文件:在.cpp文件中 #pragma comment(lib."json_vc71_libmt.lib"),在工程属性中Linker下Input中Additional Dependencies写入lib文件名字(Release下为 json_vc71_libmt.lib,Debug为 json_vc71_libmtd.lib

注意: Jsoncpp的lib工程编译选项要和VS工程中的编译选项保持一致。如lib文件工程编译选项为MT(或MTd),VS工程中也要选择MT (或MTd),否则会出现编译错误问题,debug和release下生成的lib文件名字不同,注意不要看错了,当成一个文件来使用(我就犯了这个错误)。

方法二:使用Jsoncpp包中的.cpp .h文件
       解压上面下载的 Jsoncpp 文件,把 jsoncpp-src-0.5.0文件拷贝到工程目录下, jsoncpp-src-0.5.0\jsoncpp-src-0.5.0\include\json jsoncpp-src-0.5.0\jsoncpp-src-0.5.0\src\lib_json 目录里的文件包含到VS工程中,在VS工程的属性C/C++下General中 Additional Include Directories 包含头文件目录 .\jsoncpp-src-0.5.0\include 。在使用的cpp文件中 包含json头文件即可,如: #include "json/json.h" 。将 json_reader.cpp、 json_value.cpp和 json_writer.cpp三个文件的Precompiled Header属性设置为 Not Using Precompiled Headers 否则编译会出现错误。

jsoncpp 使用详解

jsoncpp 主要包含三种类型的 class:Value、Reader、Writer。jsoncpp 中所有对象、类名都在 namespace Json 中,包含 json.h 即可。

Json::Value 只能处理 ANSI 类型的字符串,如果 C++ 程序是用 Unicode 编码的,最好加一个 Adapt 类来适配。

// TestJsoncppCode.cpp : Defines the entry point for the console application.  
02.//  
03.  
04.#include "stdafx.h"  
05.  
06.  
07.#include "include/json/json.h"  
08.#include <fstream>  
09.#include <string>  
10.  
11.#pragma comment(lib,"lib_json.lib")  
12.using namespace std;  
13.  
14.#ifdef _DEBUG  
15.#define new DEBUG_NEW  
16.#endif  
17.  
18.  
19.// The one and only application object  
20.  
21.  
22.void WriteJsonData(const char* filename)  
23.{  
24.    Json::Reader reader;  
25.    Json::Value root; // Json::Value是一种很重要的类型,可以代表任意类型。如int, string, object, array...          
26.  
27.    std::ifstream is;  
28.    is.open(filename, std::ios::binary);  
29.    if (reader.parse(is, root))  
30.    {  
31.        Json::Value arrayObj;   // 构建对象    
32.        Json::Value new_item, new_item1;  
33.        new_item["date"] = "2011-11-11";  
34.        new_item1["time"] = "11:11:11";  
35.        arrayObj.append(new_item);  // 插入数组成员    
36.        arrayObj.append(new_item1); // 插入数组成员    
37.        int file_size = root["files"].size();  
38.        for (int i = 0; i < file_size; ++i)  
39.            root["files"][i]["exifs"] = arrayObj;   // 插入原json中   
40.        std::string out = root.toStyledString();  
41.        // 输出无格式json字符串    
42.        Json::FastWriter writer;  
43.        std::string strWrite = writer.write(root);  
44.        std::ofstream ofs;  
45.        ofs.open("test_write.json");  
46.        ofs << strWrite;  
47.        ofs.close();  
48.    }  
49.  
50.    is.close();  
51.}  
52.  
53.int ReadJsonFromFile(const char* filename)  
54.{  
55.    Json::Reader reader;// 解析json用Json::Reader     
56.    Json::Value root; // Json::Value是一种很重要的类型,可以代表任意类型。如int, string, object, array...           
57.  
58.    std::ifstream is;  
59.    is.open(filename, std::ios::binary);  
60.    if (reader.parse(is, root, false))  
61.    {  
62.        std::string code;  
63.        if (!root["files"].isNull())  // 访问节点,Access an object value by name, create a null member if it does not exist.    
64.            code = root["uploadid"].asString();  
65.  
66.        code = root.get("uploadid", "null").asString();// 访问节点,Return the member named key if it exist, defaultValue otherwise.      
67.  
68.        int file_size = root["files"].size();  // 得到"files"的数组个数    
69.        for (int i = 0; i < file_size; ++i)  // 遍历数组    
70.        {  
71.            Json::Value val_image = root["files"][i]["images"];  
72.            int image_size = val_image.size();  
73.            for (int j = 0; j < image_size; ++j)  
74.            {  
75.                std::string type = val_image[j]["type"].asString();  
76.                std::string url = val_image[j]["url"].asString();  
77.                printf("type : %s, url : %s \n", type.c_str(), url.c_str());  
78.            }  
79.        }  
80.    }  
81.    is.close();  
82.  
83.    return 0;  
84.}  
85.  
86.int main(int argc, TCHAR* argv[], TCHAR* envp[])  
87.{  
88.    int nRetCode = 0;  
89.  
90.  
91.    //1.从字符串解析json  
92.    const char* str = "{\"uploadid\": \"UP000000\",\"code\": 100,\"msg\": \"\",\"files\": \"\"}";  
93.  
94.    Json::Reader reader;  
95.    Json::Value root;  
96.    if (reader.parse(str, root))    // reader将Json字符串解析到root,root将包含Json里所有子元素    
97.    {  
98.        printf("--------------从字符串读取JSON---------------\n");  
99.        std::string upload_id = root["uploadid"].asString();  // 访问节点,upload_id = "UP000000"    
100.        int code = root["code"].asInt();                      // 访问节点,code = 100   
101.  
102.        printf("upload_id : %s\ncode : %d \n", upload_id.c_str(), code);  
103.    }  
104.  
105.    //2.从文件解析json  
106.    string sTempPath = "test_json.json";  
107.  
108.    printf("--------------从文件读取JSON---------------\n");  
109.    ReadJsonFromFile(sTempPath.c_str());  
110.  
111.  
112.    //3.向文件写入json  
113.    WriteJsonData(sTempPath.c_str());  
114.  
115.    system("pause");  
116.  
117.    return nRetCode;  
118.}  



### 如何使用C++解析JSON文件 在C++解析JSON文件可以通过多种第三方库实现,其中最常用的两种库分别是`jsoncpp`和`rapidjson`。以下是这两种库的具体介绍以及它们的使用方法。 #### jsoncpp 库 `jsoncpp` 是一种功能强大且易于使用的 JSON 解析库,支持读取、写入和操作 JSON 数据结构。它提供了简单易懂的 API 接口来处理复杂的嵌套数据[^1]。 要使用 `jsoncpp` 进行 JSON 文件解析,通常需要以下几个步骤: 1. **安装并配置库** 如果是在 Windows 平台上开发,可以直接通过 Visual Studio 的 NuGet 包管理器下载 `jsoncpp`;如果是 Linux,则可以按照以下方式构建静态库: ```bash mkdir -p build/debug cd build/debug cmake -DCMAKE_BUILD_TYPE=debug -DBUILD_STATIC_LIBS=ON -DBUILD_SHARED_LIBS=OFF -DARCHIVE_INSTALL_DIR=. -G "Unix Makefiles" ../.. make ``` 2. **编写代码示例** 下面是一个简单的例子展示如何利用 `jsoncpp` 来解析 JSON 文件中的学生信息[^3]: ```cpp #include <iostream> #include <fstream> #include <vector> #include <json/json.h> struct Score { std::string subject; float score; bool bChecked; Score(const std::string& sub, const float sc, const bool checked) : subject(sub), score(sc), bChecked(checked) {} }; struct Student { std::string name; std::vector<Score> arr; }; class JsoncppAssistant { public: bool Read(std::vector<Student>& arr, const std::string& path) { arr.clear(); Json::Reader reader; Json::Value root; std::ifstream ifs(path); if (!ifs.is_open()) return false; if (!reader.parse(ifs, root)) return false; if (root["data"].isNull()) return false; int nSize = root["data"].size(); for (int i = 0; i < nSize; ++i) { Student stu; stu.name = root["data"][i]["name"].asString(); if (!root["data"][i]["Score"].isNull()) { int nSz2 = root["data"][i]["Score"].size(); stu.arr.reserve(nSz2); for (int j = 0; j < nSz2; ++j) { stu.arr.emplace_back( root["data"][i]["Score"][j]["subject"].asString(), root["data"][i]["Score"][j]["score"].asFloat(), root["data"][i]["Score"][j]["bChecked"].asBool() ); } } arr.push_back(stu); } return true; } }; int main() { std::vector<Student> students; JsoncppAssistant assistant; if (assistant.Read(students, "test.json")) { for (const auto& student : students) { std::cout << "Name: " << student.name << "\n"; for (const auto& score : student.arr) { std::cout << "Subject: " << score.subject << ", Score: " << score.score << ", Checked: " << (score.bChecked ? "Yes" : "No") << "\n"; } } } else { std::cerr << "Failed to read or parse the file.\n"; } return 0; } ``` #### rapidjson 库 另一种流行的 JSON 处理库是 `rapidjson`,它的特点是性能优越并且轻量级。该库允许开发者快速高效地解析 JSON 文档,并提供灵活的数据访问接口[^2]。 下面是如何使用 `rapidjson` 编写的另一个示例程序: ```cpp #include <iostream> #include <vector> #include <rapidjson/document.h> #include <rapidjson/filereadstream.h> struct Score { std::string subject; double score; bool isChecked; }; struct Student { std::string name; std::vector<Score> scores; }; bool ParseStudents(const char* filePath, std::vector<Student>& students) { FILE* fp = fopen(filePath, "rb"); if (!fp) return false; char buffer[65536]; rapidjson::FileReadStream is(fp, buffer, sizeof(buffer)); rapidjson::Document doc; doc.ParseStream(is); fclose(fp); if (!doc.IsObject() || !doc.HasMember("data") || !doc["data"].IsArray()) return false; for (auto&& item : doc["data"].GetArray()) { if (!item.IsObject() || !item.HasMember("name")) continue; Student s; s.name = item["name"].GetString(); if (item.HasMember("Score") && item["Score"].IsArray()) { for (auto&& scoreItem : item["Score"].GetArray()) { if (!scoreItem.IsObject() || !scoreItem.HasMember("subject") || !scoreItem["subject"].IsString() || !scoreItem.HasMember("score") || !scoreItem["score"].IsDouble() || !scoreItem.HasMember("bChecked") || !scoreItem["bChecked"].IsBool()) continue; s.scores.emplace_back(Score{ scoreItem["subject"].GetString(), scoreItem["score"].GetDouble(), scoreItem["bChecked"].GetBool() }); } } students.push_back(s); } return true; } int main() { std::vector<Student> students; if (ParseStudents("test.json", students)) { for (const auto& student : students) { std::cout << "Student Name: " << student.name << '\n'; for (const auto& score : student.scores) { std::cout << "- Subject: " << score.subject << ", Score: " << score.score << ", Is Checked: " << (score.isChecked ? "True" : "False") << '\n'; } } } else { std::cerr << "Error parsing JSON\n"; } return 0; } ``` 以上两个示例分别展示了如何基于不同的库完成相同的功能需求——即从 JSON 文件中提取学生的成绩记录。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值