最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++讀取JSON文件的三種方式小結(jié)(jsoncpp、nlohmann/json和RapidJSON)

 更新時間:2026年01月07日 10:06:43   作者:司徒軒宇  
JSON已成為最流行的數(shù)據(jù)交換格式之一,,C++標準庫并沒有提供原生的JSON支持,這就需要我們借助第三方庫來處理JSON數(shù)據(jù),下面就來介紹一下讀取JSON文件的三種方式,感興趣的可以了解一下

在現(xiàn)代C++開發(fā)中,JSON(JavaScript Object Notation)已成為最流行的數(shù)據(jù)交換格式之一。無論是網(wǎng)絡(luò)通信、配置文件讀取還是數(shù)據(jù)持久化,JSON都扮演著重要角色。然而,C++標準庫并沒有提供原生的JSON支持,這就需要我們借助第三方庫來處理JSON數(shù)據(jù)。

本文將詳細介紹三種主流的C++ JSON庫:jsoncpp、nlohmann/jsonRapidJSON,通過實際代碼示例展示如何使用它們讀取和解析JSON文件。

為什么需要JSON庫?

JSON以其輕量級、易讀易寫的特性,在Web API、配置文件、數(shù)據(jù)存儲等場景中廣泛應用。在C++中處理JSON數(shù)據(jù)時,我們需要解決以下問題:

  • 解析JSON字符串或文件
  • 驗證JSON格式的正確性
  • 訪問和修改JSON數(shù)據(jù)
  • 將C++數(shù)據(jù)結(jié)構(gòu)序列化為JSON

下面讓我們深入了解這三種庫的具體用法。

1. jsoncpp - 經(jīng)典穩(wěn)定的選擇

jsoncpp是一個歷史悠久、穩(wěn)定可靠的C++ JSON庫,被許多大型項目使用。

安裝與配置

Ubuntu/Debian:

sudo apt-get install libjsoncpp-dev

源碼編譯:

git clone https://github.com/open-source-parsers/jsoncpp.git
cd jsoncpp
mkdir build && cd build
cmake .. && make && sudo make install

基本使用方法

#include <json/json.h>
#include <fstream>
#include <iostream>
#include <vector>

class JsonCppExample {
public:
    void readJsonFile(const std::string& filename) {
        // 打開文件
        std::ifstream file(filename);
        if (!file.is_open()) {
            std::cerr << "錯誤:無法打開文件 " << filename << std::endl;
            return;
        }

        // 創(chuàng)建JSON讀取器
        Json::CharReaderBuilder readerBuilder;
        Json::Value root;  // 存儲解析后的 JSON 數(shù)據(jù)
        std::string errs;  // 存儲錯誤信息

        // 解析JSON
        bool success = Json::parseFromStream(readerBuilder, file, &root, &errs);
        if (!success) {
            std::cerr << "JSON解析錯誤: " << errs << std::endl;
            return;
        }

        // 訪問基本數(shù)據(jù)類型
        if (root.isMember("name")) {
            std::string name = root["name"].asString(); //訪問字符串類型
            std::cout << "姓名: " << name << std::endl;
        }

        if (root.isMember("age")) {
            int age = root["age"].asInt();  //訪問整數(shù)類型
            std::cout << "年齡: " << age << std::endl;
        }

        if (root.isMember("is_student")) {
            bool isStudent = root["is_student"].asBool(); //訪問布爾類型
            std::cout << "是否學生: " << (isStudent ? "是" : "否") << std::endl;
        }

        // 訪問數(shù)組
        if (root.isMember("hobbies") && root["hobbies"].isArray()) {
            std::cout << "愛好: ";
            //訪問數(shù)組類型
            for (const auto& hobby : root["hobbies"]) {
                std::cout << hobby.asString() << " ";  
            }
            std::cout << std::endl;
        }

        // 訪問嵌套對象
        if (root.isMember("address")) {
            Json::Value address = root["address"];
            if (address.isMember("street")) {
                std::cout << "街道: " << address["street"].asString() << std::endl;
            }
            if (address.isMember("city")) {
                std::cout << "城市: " << address["city"].asString() << std::endl;
            }
        }

        // 安全訪問,提供默認值
        double height = root.get("height", 170.0).asDouble();
        std::cout << "身高: " << height << "cm" << std::endl;
    }

    void writeJsonFile(const std::string& filename) {
        Json::Value root;
        
        // 設(shè)置基本值
        root["name"] = "李四";
        root["age"] = 30;
        root["is_student"] = false;
        
        // 設(shè)置數(shù)組
        Json::Value hobbies(Json::arrayValue);
        hobbies.append("旅游");
        hobbies.append("攝影");
        hobbies.append("烹飪");
        root["hobbies"] = hobbies;
        
        // 設(shè)置嵌套對象
        Json::Value address;
        address["street"] = "中山路456號";
        address["city"] = "上海";
        root["address"] = address;
        
        // 寫入文件
        std::ofstream file(filename);
        if (file.is_open()) {
            Json::StreamWriterBuilder writerBuilder;
            std::unique_ptr<Json::StreamWriter> writer(writerBuilder.newStreamWriter());
            writer->write(root, &file);
            file.close();
            std::cout << "JSON文件已寫入: " << filename << std::endl;
        }
    }
};

// 使用示例
int main() {
    JsonCppExample example;
    example.writeJsonFile("output.json");
    example.readJsonFile("data.json");
    return 0;
}

2. nlohmann/json - 現(xiàn)代易用的選擇

nlohmann/json是一個單頭文件的現(xiàn)代C++ JSON庫,以其簡潔的API和強大的功能而聞名。

安裝與配置

單頭文件方式(推薦):

// 只需下載一個頭文件
#include "nlohmann/json.hpp"

包管理器安裝:

# vcpkg
vcpkg install nlohmann-json

# Conan
conan install nlohmann_json/3.11.2

基本使用方法

#include <nlohmann/json.hpp>
#include <fstream>
#include <iostream>
#include <vector>

using json = nlohmann::json;

class NlohmannJsonExample {
public:
    void readJsonFile(const std::string& filename) {
        try {
            // 直接從文件讀取JSON
            std::ifstream file(filename);
            if (!file.is_open()) {
                throw std::runtime_error("無法打開文件: " + filename);
            }

            json data = json::parse(file);

            // 訪問基本數(shù)據(jù)類型 - 方式1:直接訪問
            std::string name = data["name"];
            int age = data["age"];
            bool isStudent = data["is_student"];
            
            std::cout << "姓名: " << name << std::endl;
            std::cout << "年齡: " << age << std::endl;
            std::cout << "是否學生: " << (isStudent ? "是" : "否") << std::endl;

            // 訪問基本數(shù)據(jù)類型 - 方式2:帶默認值的安全訪問
            double height = data.value("height", 175.5);
            std::cout << "身高: " << height << "cm" << std::endl;

            // 訪問數(shù)組
            std::cout << "愛好: ";
            for (const auto& hobby : data["hobbies"]) {
                std::cout << hobby.get<std::string>() << " ";
            }
            std::cout << std::endl;

            // 訪問嵌套對象
            if (data.contains("address")) {
                auto& address = data["address"];
                std::cout << "地址: " << address["city"] << ", " << address["street"] << std::endl;
            }

            // 類型檢查和異常安全
            if (data["hobbies"].is_array()) {
                std::cout << "hobbies 是數(shù)組類型" << std::endl;
            }

            // 更復雜的遍歷
            std::cout << "\n所有數(shù)據(jù):" << std::endl;
            for (auto& [key, value] : data.items()) {
                std::cout << key << ": " << value << std::endl;
            }

        } catch (const json::parse_error& e) {
            std::cerr << "JSON解析錯誤: " << e.what() << std::endl;
        } catch (const json::type_error& e) {
            std::cerr << "類型錯誤: " << e.what() << std::endl;
        } catch (const std::exception& e) {
            std::cerr << "錯誤: " << e.what() << std::endl;
        }
    }

    void writeJsonFile(const std::string& filename) {
        // 創(chuàng)建JSON對象 - 方式1:類似字典操作
        json data;
        data["name"] = "王五";
        data["age"] = 28;
        data["is_student"] = true;
        data["height"] = 180.2;

        // 創(chuàng)建數(shù)組
        data["hobbies"] = {"音樂", "電影", "運動"};

        // 創(chuàng)建嵌套對象
        data["address"] = {
            {"street", "解放路789號"},
            {"city", "廣州"},
            {"postcode", "510000"}
        };

        // 添加復雜結(jié)構(gòu)
        data["scores"] = {
            {"數(shù)學", 95},
            {"英語", 88},
            {"物理", 92}
        };

        // 寫入文件,美化輸出
        std::ofstream file(filename);
        if (file.is_open()) {
            file << data.dump(4); // 縮進4個空格
            std::cout << "JSON文件已寫入: " << filename << std::endl;
        }
    }

    // 高級功能:C++類型與JSON自動轉(zhuǎn)換
    struct Person {
        std::string name;
        int age;
        bool is_student;
        std::vector<std::string> hobbies;
        
        // 必須提供to_json和from_json函數(shù)
        NLOHMANN_DEFINE_TYPE_INTRUSIVE(Person, name, age, is_student, hobbies)
    };

    void useWithCustomType() {
        // 從JSON自動轉(zhuǎn)換到C++結(jié)構(gòu)體
        json j = R"({
            "name": "趙六",
            "age": 35,
            "is_student": false,
            "hobbies": ["讀書", "寫作"]
        })"_json;

        Person person = j.get<Person>();
        std::cout << "自定義類型姓名: " << person.name << std::endl;

        // 從C++結(jié)構(gòu)體自動轉(zhuǎn)換到JSON
        Person newPerson{"錢七", 40, true, {"編程", "數(shù)學"}};
        json newJson = newPerson;
        std::cout << "生成的JSON: " << newJson.dump(2) << std::endl;
    }
};

// 使用示例
int main() {
    NlohmannJsonExample example;
    example.writeJsonFile("nlohmann_output.json");
    example.readJsonFile("data.json");
    example.useWithCustomType();
    return 0;
}

編譯命令

# 單頭文件方式,只需包含路徑
g++ -o nlohmann_example nlohmann_example.cpp -std=c++17

# 如果有安裝到系統(tǒng)目錄,則不需要特殊參數(shù)
g++ -o nlohmann_example nlohmann_example.cpp

3. RapidJSON - 高性能的選擇

RapidJSON專注于高性能和低內(nèi)存占用,特別適合對性能要求嚴格的場景。

安裝與配置

源碼集成:

git clone https://github.com/Tencent/rapidjson.git

包管理器:

# vcpkg
vcpkg install rapidjson

基本使用方法

#include "rapidjson/document.h"
#include "rapidjson/istreamwrapper.h"
#include "rapidjson/ostreamwrapper.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"
#include <fstream>
#include <iostream>
#include <vector>

class RapidJsonExample {
public:
    void readJsonFile(const std::string& filename) {
        // 打開文件
        std::ifstream ifs(filename);
        if (!ifs.is_open()) {
            std::cerr << "錯誤:無法打開文件 " << filename << std::endl;
            return;
        }

        // 使用流包裝器讀取JSON
        rapidjson::IStreamWrapper isw(ifs);
        rapidjson::Document document;
        
        // 解析JSON
        document.ParseStream(isw);
        
        // 檢查解析錯誤
        if (document.HasParseError()) {
            std::cerr << "解析錯誤 (offset " << document.GetErrorOffset() 
                      << "): " << rapidjson::GetParseError_En(document.GetParseError()) 
                      << std::endl;
            return;
        }

        // 檢查根對象類型
        if (!document.IsObject()) {
            std::cerr << "錯誤:根元素不是對象" << std::endl;
            return;
        }

        // 安全訪問字符串成員
        if (document.HasMember("name") && document["name"].IsString()) {
            std::string name = document["name"].GetString();
            std::cout << "姓名: " << name << std::endl;
        }

        // 安全訪問整數(shù)成員
        if (document.HasMember("age") && document["age"].IsInt()) {
            int age = document["age"].GetInt();
            std::cout << "年齡: " << age << std::endl;
        }

        // 安全訪問布爾成員
        if (document.HasMember("is_student") && document["is_student"].IsBool()) {
            bool isStudent = document["is_student"].GetBool();
            std::cout << "是否學生: " << (isStudent ? "是" : "否") << std::endl;
        }

        // 訪問數(shù)組
        if (document.HasMember("hobbies") && document["hobbies"].IsArray()) {
            const rapidjson::Value& hobbies = document["hobbies"];
            std::cout << "愛好: ";
            for (rapidjson::SizeType i = 0; i < hobbies.Size(); i++) {
                if (hobbies[i].IsString()) {
                    std::cout << hobbies[i].GetString() << " ";
                }
            }
            std::cout << std::endl;
        }

        // 訪問嵌套對象
        if (document.HasMember("address") && document["address"].IsObject()) {
            const rapidjson::Value& address = document["address"];
            if (address.HasMember("street") && address["street"].IsString()) {
                std::cout << "街道: " << address["street"].GetString() << std::endl;
            }
            if (address.HasMember("city") && address["city"].IsString()) {
                std::cout << "城市: " << address["city"].GetString() << std::endl;
            }
        }

        // 處理可能不存在的字段(帶默認值)
        double height = 170.0; // 默認值
        if (document.HasMember("height") && document["height"].IsDouble()) {
            height = document["height"].GetDouble();
        }
        std::cout << "身高: " << height << "cm" << std::endl;
    }

    void writeJsonFile(const std::string& filename) {
        rapidjson::Document document;
        document.SetObject();
        rapidjson::Document::AllocatorType& allocator = document.GetAllocator();

        // 添加字符串成員
        rapidjson::Value name;
        name.SetString("孫八", allocator);
        document.AddMember("name", name, allocator);

        // 添加數(shù)字成員
        document.AddMember("age", 22, allocator);
        document.AddMember("height", 175.5, allocator);

        // 添加布爾成員
        document.AddMember("is_student", true, allocator);

        // 添加數(shù)組
        rapidjson::Value hobbies(rapidjson::kArrayType);
        rapidjson::Value hobby1, hobby2, hobby3;
        hobby1.SetString("游戲", allocator);
        hobby2.SetString("編程", allocator);
        hobby3.SetString("音樂", allocator);
        hobbies.PushBack(hobby1, allocator);
        hobbies.PushBack(hobby2, allocator);
        hobbies.PushBack(hobby3, allocator);
        document.AddMember("hobbies", hobbies, allocator);

        // 添加嵌套對象
        rapidjson::Value address(rapidjson::kObjectType);
        rapidjson::Value street, city;
        street.SetString("和平路101號", allocator);
        city.SetString("深圳", allocator);
        address.AddMember("street", street, allocator);
        address.AddMember("city", city, allocator);
        document.AddMember("address", address, allocator);

        // 寫入文件
        std::ofstream ofs(filename);
        if (ofs.is_open()) {
            rapidjson::OStreamWrapper osw(ofs);
            rapidjson::Writer<rapidjson::OStreamWrapper> writer(osw);
            document.Accept(writer);
            std::cout << "JSON文件已寫入: " << filename << std::endl;
        }
    }

    // 高級用法:使用StringBuffer
    void useStringBuffer() {
        rapidjson::Document document;
        document.SetObject();
        rapidjson::Document::AllocatorType& allocator = document.GetAllocator();

        document.AddMember("message", "Hello, RapidJSON!", allocator);
        document.AddMember("value", 42, allocator);

        // 使用StringBuffer生成JSON字符串
        rapidjson::StringBuffer buffer;
        rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
        document.Accept(writer);

        std::cout << "生成的JSON字符串: " << buffer.GetString() << std::endl;
    }
};

// 使用示例
int main() {
    RapidJsonExample example;
    example.writeJsonFile("rapidjson_output.json");
    example.readJsonFile("data.json");
    example.useStringBuffer();
    return 0;
}

編譯命令

g++ -o rapidjson_example rapidjson_example.cpp -I/path/to/rapidjson/include

三種庫的詳細對比

為了幫助您選擇合適的JSON庫,下面從多個維度進行詳細對比:

性能對比

測試場景jsoncppnlohmann/jsonRapidJSON
解析速度中等較慢最快
內(nèi)存占用中等較高最低
序列化速度中等較慢最快

API易用性對比

特性jsoncppnlohmann/jsonRapidJSON
學習曲線平緩非常平緩陡峭
代碼簡潔性中等最優(yōu)繁瑣
類型安全中等優(yōu)秀需要手動檢查
錯誤處理返回bool異常機制返回錯誤碼

到此這篇關(guān)于C++讀取JSON文件的三種方式小結(jié)(jsoncpp、nlohmann/json和RapidJSON)的文章就介紹到這了,更多相關(guān)C++讀取JSON內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Pipes實現(xiàn)LeetCode(193.驗證電話號碼)

    Pipes實現(xiàn)LeetCode(193.驗證電話號碼)

    這篇文章主要介紹了Pipes實現(xiàn)LeetCode(193.驗證電話號碼),本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • C++微服務(wù)UserServer設(shè)計與實現(xiàn)方法詳解

    C++微服務(wù)UserServer設(shè)計與實現(xiàn)方法詳解

    在當今云原生時代,微服務(wù)架構(gòu)已成為構(gòu)建大規(guī)模分布式系統(tǒng)的主流選擇,下面這篇文章主要介紹了C++微服務(wù)UserServer設(shè)計與實現(xiàn)的相關(guān)資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2025-11-11
  • C/C++?Qt數(shù)據(jù)庫與SqlTableModel組件應用教程

    C/C++?Qt數(shù)據(jù)庫與SqlTableModel組件應用教程

    SqlTableModel?組件可以將數(shù)據(jù)庫中的特定字段動態(tài)顯示在TableView表格組件中,這篇文章將主要介紹SqlTableModel組件一些常用的操作,需要的朋友可以參考一下
    2021-12-12
  • 詳解C++17中類模板參數(shù)推導的使用

    詳解C++17中類模板參數(shù)推導的使用

    自C++17起就通過使用類模板參數(shù)推導,只要編譯器能根據(jù)初始值推導出所有模板參數(shù),那么就可以不指明參數(shù),下面我們就來看看C++17中類模板參數(shù)推導的具體使用吧
    2024-03-03
  • vs2019創(chuàng)建WebService服務(wù)的實現(xiàn)

    vs2019創(chuàng)建WebService服務(wù)的實現(xiàn)

    這篇文章主要介紹了vs2019創(chuàng)建WebService服務(wù)的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-03-03
  • C++智能指針模板應用詳細介紹

    C++智能指針模板應用詳細介紹

    從比較簡單的層面來看,智能指針是RAII(Resource Acquisition Is Initialization,資源獲取即初始化)機制對普通指針進行的一層封裝。這樣使得智能指針的行為動作像一個指針,本質(zhì)上卻是一個對象,這樣可以方便管理一個對象的生命周期
    2022-08-08
  • C語言線程池的常見實現(xiàn)方式詳解

    C語言線程池的常見實現(xiàn)方式詳解

    本文介紹了如何使用 C 語言實現(xiàn)一個基本的線程池,線程池的實現(xiàn)包括工作線程、任務(wù)隊列、任務(wù)調(diào)度、線程池的初始化、任務(wù)添加、銷毀等步驟,感興趣的朋友跟隨小編一起看看吧
    2025-01-01
  • C++?primer超詳細講解關(guān)聯(lián)容器

    C++?primer超詳細講解關(guān)聯(lián)容器

    兩個主要的關(guān)聯(lián)容器為map和set,map中元素是一些關(guān)鍵字—值對,關(guān)鍵字起索引的作用,值則表示與索引相關(guān)聯(lián)的數(shù)據(jù)。set中每個元素只包含一個關(guān)鍵字,set支持高效的關(guān)鍵字查詢操作——檢查一個給定關(guān)鍵字是否在set中
    2022-07-07
  • C語言實現(xiàn)學生獎學金評定系統(tǒng)

    C語言實現(xiàn)學生獎學金評定系統(tǒng)

    這篇文章主要介紹了C語言實現(xiàn)學生獎學金評定系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • C++11 并發(fā)指南之std::mutex詳解

    C++11 并發(fā)指南之std::mutex詳解

    這篇文章主要介紹了C++11 并發(fā)指南之std::mutex詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-02-02

最新評論

上思县| 沅江市| 前郭尔| 化隆| 中西区| 泰安市| 洛隆县| 宁河县| 翼城县| 旺苍县| 盐源县| 建始县| 镇江市| 阿荣旗| 子洲县| 崇信县| 保山市| 星子县| 临汾市| 盐边县| 周宁县| 合水县| 遂川县| 新和县| 晋江市| 托里县| 新泰市| 宣威市| 泊头市| 马鞍山市| 扎鲁特旗| 西林县| 廊坊市| 兴化市| 武鸣县| 沙田区| 襄垣县| 德州市| 长沙县| 中山市| 乌兰县|