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

简介

  • 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;
    }

附件

  • josncpp源码
    https://github.com/open-source-parsers/jsoncpp
  • 文档
    https://open-source-parsers.github.io/jsoncpp-docs/doxygen/files.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/760939.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

PC系统安装引导:2、进入维护环境

目录 &#x1f345;点击这里查看所有博文 闲来无事&#xff0c;记录下自己以往多年总结出的一套系统维护的方法。以供有需要的人学习使用。例如&#xff0c;系统崩溃了无法启动怎么办&#xff0c;如何重做系统&#xff0c;如何安装双系统&#xff0c;如何引导多系统&#xff0…

F_SETFL的例子

代码; #include <unistd.h> #include <fcntl.h> #include <stdio.h> #include <string.h>int main(void) {int flags-1;char buf[]"FCNTL";int fdopen("test.txt",O_RDWR);flagsfcntl(fd,F_GETFL,0);flags|O_APPEND;flagsfcntl(f…

如何完成域名解析验证

一&#xff1a;什么是DNS解析&#xff1a; DNS解析是互联网上将人类可读的域名&#xff08;如www.example.com&#xff09;转换为计算机可识别的IP地址&#xff08;如192.0.2.1&#xff09;的过程&#xff0c;大致遵循以下步骤&#xff1a; 查询本地缓存&#xff1a;当用户尝…

Python28-4 KNN近邻算法

KNN&#xff08;K-Nearest Neighbors&#xff09;算法是一种常用的机器学习算法&#xff0c;主要用于分类和回归问题。 1. KNN算法的基本概念 KNN算法是一种基于实例的学习算法&#xff0c;也称为惰性学习&#xff08;Lazy Learning&#xff09;算法&#xff0c;因为它在训练…

快递物流仓库管理系统java项目springboot和vue的前后端分离系统java课程设计java毕业设计

文章目录 快递物流仓库管理系统一、项目演示二、项目介绍三、部分功能截图四、部分代码展示五、底部获取项目源码&#xff08;9.9&#xffe5;带走&#xff09; 快递物流仓库管理系统 一、项目演示 快递物流仓库管理系统 二、项目介绍 语言: Java 数据库&#xff1a;MySQL 前…

苹果手机图片识别文字出现日期?这里教你如何调整

一、问题原因分析 首先&#xff0c;我们需要理解为什么会出现这种情况。通常&#xff0c;苹果手机在识别图片中的文字时&#xff0c;会根据图片的内容和上下文来显示相关信息。如果图片中包含明显的日期信息&#xff0c;或者手机的某些设置将图片识别与日期显示相关联&#xf…

MicroBin好用的粘贴板工具

有时候你可能想从一台电脑上粘贴文本到另一台电脑上&#xff0c;或者是你想要分享一张图片或者是一些文件&#xff0c;某些设备上登陆qq和微信有不太方便&#xff0c;那么就可以使用MicroBin&#xff0c;它不但可以实现跨设备复制粘贴的功能&#xff0c;还支持文件上传等功能 …

Games101学习笔记 Lecture 14: Ray Tracing 2 (Acceleration Radiometry)

Lecture 14: Ray Tracing 2 (Acceleration & Radiometry 一、加速光线追踪 AABB1.均匀网格 Uniform Spatial Partitions (Grids)①前处理-构建加速网格②射线与场景相交③网格分辨率④适用情况 2.空间划分KD-Tree①预处理②数据结构③遍历④问题 3.对象划分 & 包围盒层…

表单外链,支持查看方式设置

06/19 主要更新模块概览 外链设置 跳转缩放 打印调整 数据校验 01 表单管理 1.1 【表单外链】-填写外链新增查看方式设置 说明&#xff1a; 原表单填写外链&#xff0c;填写字段权限和查看权限统一字段设置&#xff0c;用户在填写时看到数据与查看数据一致…

Python | 基于支持向量机(SVM)的图像分类案例

支持向量机&#xff08;SVM&#xff09;是一种监督机器学习算法&#xff0c;可用于分类和回归任务。在本文中&#xff0c;我们将重点关注使用SVM进行图像分类。 当计算机处理图像时&#xff0c;它将其视为二维像素阵列。数组的大小对应于图像的分辨率&#xff0c;例如&#xf…

常用图片处理操作

静态图片文件转base64 import base64 with open(1.png, rb) as f:source f.read() base64_img base64.b64encode(source)base64转静态图片文件 imgdata base64.b64decode(base64_img)# 将图片保存为文件 with open("new.png", wb) as f:f.write(imgdata)PS:这里…

精密空气加热器负载组

小型便携式 &#xff1a;精密空气加热器&#xff08;负载组&#xff09;能够对数据中心热通道/冷通道冷却系统进行全面测试。EAK 是一款 19 英寸机架式设备&#xff08;10U 高&#xff09;&#xff0c;可轻松安装到各种标准服务器机架中。通过集成可调节的热量水平&#xff08;…

【计算机毕业设计】061互助学习微信小程序

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

Redis学习——Redisson 分布式锁集成及其简单使用

文章目录 引言1. Redisson概述1.1 Redisson的基本概念1.2 Redisson的主要功能1.3 Redisson的优点 2. 开发环境3. Redisson的安装与配置3.1 添加依赖3.2 配置Redisson 4. 使用Redisson4.1 可重入锁4.1.1 可重入锁的概念4.1.2 可重入锁的实现原理4.1.3 简单使用锁的获取和释放 4.…

无线麦克风哪个品牌音质最好,一篇看懂无线领夹麦克风怎么挑选

在数字化时代背景下&#xff0c;直播和个人视频日志&#xff08;Vlog&#xff09;已成为新的文化现象&#xff0c;这些趋势不仅重塑了内容创作&#xff0c;也促进了音频设备市场的繁荣。无线领夹麦克风&#xff0c;以其设计上的轻便和录音上的高效率&#xff0c;成为视频创作者…

手把手带你薅一台云服务器

前两篇&#xff0c;带着大家在自己本地搞了一台 Linux 虚拟机&#xff1a; 【保姆级教程】Windows上安装Linux子系统&#xff0c;搞台虚拟机玩玩【保姆级教程】Windows 远程登陆 Linux 服务器的两种方式&#xff1a;SSH VS Code&#xff0c;开发必备 问题来了&#xff1a;本…

nacos漏洞小结

Alibaba Nacos是阿里巴巴推出来的一个新开源项目&#xff0c;是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。致力于帮助发现、配置和管理微服务。Nacos提供了一组简单易用的特性集&#xff0c;可以快速实现动态服务发现、服务配置、服务元数据及流量管理…

51单片机第18步_将TIM0用作13位定时器

本章重点学习将TIM0用作13位定时器。 1、定时器0工作在模式0框图 2、定时器0工作在模式0举例 1、Keil C51中有一些关键字&#xff0c;需要牢记&#xff1a; interrupt 0&#xff1a;指定当前函数为外部中断0&#xff1b; interrupt 1&#xff1a;指定当前函数为定时器0中断…

onInterceptTouchEvent() 与 onTouch() 事件分析

前言 本文主要分析 onTouch() 与 onTouchEvent() 事件的差异 正文 先看布局文件&#xff1a; <?xml version"1.0" encoding"utf-8"?> <com.longzhiye.intercepttouch.MyFrameLayout xmlns:android"http://schemas.android.com/apk/res…

PointNet++论文导读

PointNet论文导读 主要改进网络结构&#xff1a;非均匀采样下的特征学习的鲁棒性利用点特征传播处理数据集分割 论文链接:https://arxiv.org/abs/1612.00593 主要改进 PointNet的基本思想是学习每个点的空间编码&#xff0c;然后将所有单个点的特征聚合成一个全局点云标签&am…