JsonCpp:更简洁的序列化及反序列化

发布于:2024-07-02 ⋅ 阅读:(20) ⋅ 点赞:(0)

简介

  • jsoncpp 提供了一组简单易用的 API,使得在 C++ 程序中处理 JSON 数据变得更加方便和高效。

安装

  • linux环境下安装jsoncpp
sudo apt-get update
sudo apt-get install --reinstall libjsoncpp-dev
  • 建立软链接确保编译器找到头文件 #include <json/json.h>
sudo ln -s /usr/include/jsoncpp/json /usr/include/json

简易demo: 基础数据读写

json数据的序列化及反序列化

/* example.cpp */ 
#include <iostream>
#include <fstream>
#include <json/json.h> // JSONcpp 头文件

bool writeJsonToFile(const std::string &filename)
{
    // 创建一个 JSON 对象
    Json::Value root;
    root["key"] = "item";
    root["value1"] = 10;
    root["value2"] = 1.2345f;
    root["value3"] = 2.3456f;

    // 将 JSON 对象转换为字符串
    Json::StreamWriterBuilder builder;
    std::string jsonString = Json::writeString(builder, root);

    // 将 JSON 字符串写入文件
    std::ofstream ofs(filename);
    if (!ofs.is_open())
    {
        std::cerr << "Failed to open file for writing: " << filename << std::endl;
        return false;
    }
    ofs << jsonString;
    ofs.close();

    std::cout << "JSON data written to file: " << filename << std::endl;
    return true;
}

bool readAndParseJsonFile(const std::string &filename)
{
    // 打开文件并读取 JSON 数据
    std::ifstream ifs(filename);
    if (!ifs.is_open())
    {
        std::cerr << "Failed to open file for reading: " << filename << std::endl;
        return false;
    }

    Json::Value root;
    Json::CharReaderBuilder readerBuilder;
    std::string errs;

    // 解析 JSON 数据
    if (!Json::parseFromStream(readerBuilder, ifs, &root, &errs))
    {
        std::cerr << "Failed to parse JSON in file: " << filename << std::endl;
        std::cerr << errs << std::endl;
        return false;
    }

    // 获取 JSON 中的字段值
    std::string key = root["key"].asString();
    int value1 = root["value1"].asInt();
    float value2 = root["value2"].asFloat();
    double value3 = root["value3"].asDouble();

    // 打印解析后的值
    std::cout << "key: " << key << std::endl;
    std::cout << "value1: " << value1 << std::endl;
    std::cout << "value2: " << value2 << std::endl;
    std::cout << "value3: " << value3 << std::endl;

    return true;
}

int main()
{
    const std::string filename = "example.json";

    // 写入 JSON 数据到文件
    if (!writeJsonToFile(filename))
    {
        return 1;
    }

    // 从文件读取并解析 JSON 数据
    if (!readAndParseJsonFile(filename))
    {
        return 1;
    }

    return 0;
}

  • 编译时需链接jsoncpp库
g++ example.cpp -o example -ljsoncpp
  • result
    在这里插入图片描述

升级demo: 有层级的数据结构, 包括结构体、数组

#include <iostream>
#include <fstream>
#include <vector>
#include <json/json.h> // JSONcpp 头文件

struct SecurityConfig
{
    std::string username;
    std::string password;
};

struct ServerConfig
{
    std::string address;
    int port;
    int timeout;
    SecurityConfig securityConfig;
};

struct FeatureFlags
{
    bool enableFeature;
};

bool writeConfigToFile(const std::string &filename, const ServerConfig &serverConfig, const std::vector<FeatureFlags> &featureFlagsList)
{
    // 创建一个 JSON 对象
    Json::Value root;

    // 构建服务器配置节点
    Json::Value serverNode;
    serverNode["address"] = serverConfig.address;
    serverNode["port"] = serverConfig.port;
    serverNode["timeout"] = serverConfig.timeout;

    // 构建安全配置节点
    Json::Value securityNode;
    securityNode["username"] = serverConfig.securityConfig.username;
    securityNode["password"] = serverConfig.securityConfig.password;
    serverNode["securityConfig"] = securityNode;

    root["server"] = serverNode;

    // 构建功能开关配置节点数组
    Json::Value featuresArray(Json::arrayValue);
    for (const auto &flags : featureFlagsList)
    {
        Json::Value featureNode;
        featureNode["enableFeature"] = flags.enableFeature;
        featuresArray.append(featureNode);
    }
    root["featureFlags"] = featuresArray;

    // 将 JSON 对象转换为字符串
    Json::StreamWriterBuilder builder;
    std::string jsonString = Json::writeString(builder, root);

    // 将 JSON 字符串写入文件
    std::ofstream ofs(filename);
    if (!ofs.is_open())
    {
        std::cerr << "Failed to open file for writing: " << filename << std::endl;
        return false;
    }
    ofs << jsonString;
    ofs.close();

    std::cout << "JSON data written to file: " << filename << std::endl;
    return true;
}

bool readConfigFromFile(const std::string &filename, ServerConfig &serverConfig, std::vector<FeatureFlags> &featureFlagsList)
{
    // 打开文件并读取 JSON 数据
    std::ifstream ifs(filename);
    if (!ifs.is_open())
    {
        std::cerr << "Failed to open file: " << filename << std::endl;
        return false;
    }

    // 解析 JSON 数据
    Json::Value root;
    Json::CharReaderBuilder readerBuilder;
    std::string errs;

    if (!Json::parseFromStream(readerBuilder, ifs, &root, &errs))
    {
        std::cerr << "Failed to parse JSON in file: " << filename << std::endl;
        std::cerr << errs << std::endl;
        return false;
    }

    // 解析服务器配置
    if (root.isMember("server"))
    {
        Json::Value serverNode = root["server"];
        serverConfig.address = serverNode["address"].asString();
        serverConfig.port = serverNode["port"].asInt();
        serverConfig.timeout = serverNode["timeout"].asInt();

        // 解析安全配置
        if (serverNode.isMember("securityConfig"))
        {
            Json::Value securityNode = serverNode["securityConfig"];
            serverConfig.securityConfig.username = securityNode["username"].asString();
            serverConfig.securityConfig.password = securityNode["password"].asString();
        }
        else
        {
            std::cerr << "Missing 'securityConfig' in JSON file." << std::endl;
            return false;
        }
    }
    else
    {
        std::cerr << "Missing 'server' configuration in JSON file." << std::endl;
        return false;
    }

    // 解析功能开关配置数组
    if (root.isMember("featureFlags"))
    {
        Json::Value featuresArray = root["featureFlags"];
        if (featuresArray.isArray())
        {
            for (const auto &featureNode : featuresArray)
            {
                FeatureFlags flags;
                flags.enableFeature = featureNode["enableFeature"].asBool();
                featureFlagsList.push_back(flags);
            }
        }
        else
        {
            std::cerr << "'featureFlags' is not an array in JSON file." << std::endl;
            return false;
        }
    }
    else
    {
        std::cerr << "Missing 'featureFlags' configuration in JSON file." << std::endl;
        return false;
    }

    return true;
}

int main()
{
    const std::string filename = "config.json";
    ServerConfig serverConfig = {"127.0.0.1", 8080, 5000, {"admin", "password"}};
    std::vector<FeatureFlags> featureFlagsList = {
        {true},
        {false},
        {true}};

    // 将配置写入 JSON 文件
    if (!writeConfigToFile(filename, serverConfig, featureFlagsList))
    {
        return 1;
    }

    std::cout << "Configuration written to file: " << filename << std::endl;

    // 从文件读取并解析 JSON 配置数据
    ServerConfig readServerConfig;
    std::vector<FeatureFlags> readFeatureFlagsList;

    if (!readConfigFromFile(filename, readServerConfig, readFeatureFlagsList))
    {
        return 1;
    }

    // 打印读取的配置信息
    std::cout << "Server Configuration:" << std::endl;
    std::cout << "  Address: " << readServerConfig.address << std::endl;
    std::cout << "  Port: " << readServerConfig.port << std::endl;
    std::cout << "  Timeout: " << readServerConfig.timeout << " ms" << std::endl;
    std::cout << "  Security Config:" << std::endl;
    std::cout << "    Username: " << readServerConfig.securityConfig.username << std::endl;
    std::cout << "    Password: " << readServerConfig.securityConfig.password << std::endl;

    std::cout << "Feature Flags:" << std::endl;
    for (size_t i = 0; i < readFeatureFlagsList.size(); ++i)
    {
        std::cout << "  Feature " << i + 1 << " Enabled: " << (readFeatureFlagsList[i].enableFeature ? "true" : "false") << std::endl;
    }

    return 0;
}

  • result
    在这里插入图片描述

节点不存在的情况

  • 节点不存在的情况会解析出默认的数据 如0或空字符串
  • 主动判断节点是否存在:
    // 访问不存在的节点
    if (root.isMember("database"))
    {
        // 这里的条件不会满足,因为 JSON 文件中没有 "database" 节点
        Json::Value dbNode = root["database"];
        // 如果不存在的节点,会得到默认值
        std::string dbName = dbNode["name"].asString(); // 返回空字符串 ""
        int dbPort = dbNode["port"].asInt();            // 返回默认的整数值 0
        std::cout << "Database Name: " << dbName << std::endl;
        std::cout << "Database Port: " << dbPort << std::endl;
    }
    else
    {
        std::cerr << "Missing 'database' configuration in JSON file." << std::endl;
    }

附件