首页 > 其他分享 >JsonCpp 笔记: 读写 Json 文件

JsonCpp 笔记: 读写 Json 文件

时间:2024-04-06 16:55:06浏览次数:22  
标签:数组 gender 读写 JsonCpp Json jsoncpp Female

JsonCpp 笔记: 读写 Json 文件

完成时间: 2024-04-06

本文主要介绍使用 JsonCpp 读写 Json 文件, JsonCpp 是 C++ 上的一个 Json 处理库

Json 的语法

如果熟悉 Json 语法, 此部分可以跳过

Json 包含两种结构:

  • 对象 (object), 它是键值对的集合 (key:value)
  • 有序数组 (array)

结构之间以逗号 , 分隔, 最后一个结构末尾不能有逗号

对象 (object)

Json 对象中的键值对是无序的 (所以称为 "集合", 数学上的集合是无序的), 包裹在一对花括号 {} 中.

键 (key)

键必须是字符串

{
    "name": "Fie",
    "gender": "Female"
}

其中 namegender 都是键值对, 之间用逗号分隔, 它们之间没有先后关系, gender 的末尾没有逗号

值 (value)

FieFemale 都是键的值 (value), 它们是字符串. 值的类型可以是:

  • 字符串 (string)
  • 数值 (number)
  • 布尔值 (true, false)
  • 空 (null)
  • 对象 (object)
  • 数组 (array)

Json 支持嵌套, 所以值的类型也可以是对象或数组, 例如

{
    "name": "Fie",
    "gender": "Female",
    "weapon": "Dagger",
    "master": {
        "name": "Sara Valestein",
        "gender": "Female",
        "occupation": "Instructor",
        "affiliation": "Thors Military Academy",
        "weapon": "Sword"
    }
}

上面键 master 的值, 又是一个对象

数组 (array)

数组是 有序 列表 (关键字: 值 & 有序)

{
    "likes": [
        "Napping",
        "Snacking",
        "Observing surroundings",
        "Practicing swordsmanship",
        "Going on missions with friends"
    ]
}

标准的 Json 语法是不允许数组独立存在的, 因为数组只是值的集合. 所以 Json 可以看作是由若干个 键值对 所组成的对象, 只不过支持嵌套, 值也可以是列表

{
    "key1": "string",
    "key2": 3.14,
    "key3": {
        "sub_key": "str1",
        "sub_key": "str2"
    },
    "key4": [
        0, 1, 2, 3, 4, 5
    ]
}

详细内容可参考 json.org

环境配置

安装

此处简单提及一下 Windows 中如何在 Visual Studio Code 上使用 JsonCpp

VS Code 文档推荐我们在 Windows 平台上使用 msys2 安装 GCC 编译器, msys2 是一个 C++ 的包管理软件. 同样地, 我们也用 msys2 安装 jsoncpp

# 搜索 jsoncpp 包
pacman -Ss jsoncpp

# output:
# mingw64/mingw-w64-x86_64-jsoncpp 1.9.5-3
#     A C++ library for interacting with JSON (mingw-w64)
# ucrt64/mingw-w64-ucrt-x86_64-jsoncpp 1.9.5-3
#     A C++ library for interacting with JSON (mingw-w64)
# clang32/mingw-w64-clang-i686-jsoncpp 1.9.5-3
#     A C++ library for interacting with JSON (mingw-w64)

pacman 是 msys2 的包管理命令, 来源于 ArchLinux, 使用上面的语句搜索 JsonCpp 包, 会返回隶属于多个环境的包, 默认情况下我们的 GCC 编译器是安装在 ucrt64 内的, 所以也安装对应的 JsonCpp

pacman -S mingw-w64-ucrt-x86_64-jsoncpp

编译选项

安装好后, 在编译时需要链接 JsonCpp. 在 .vscode 目录内, 有一个 task.json 文件, 它控制了 VS Code 如何执行生成任务. 给 GCC 编译器添加一个链接参数 -ljsoncpp, 示例如下:

"args": [
    "-fdiagnostics-color=always",
    "-g",
    "${file}",
    "-l",
    "jsoncpp",
    "-o",
    "${fileDirname}\\${fileBasenameNoExtension}.exe"
]

添加好后就可以开始学习使用 JsonCpp 了. 如果没有在编译时链接 JsonCpp, 会提示各种 未定义 错误, 例如:

undefined reference to `Json::Value::~Value()'

从文件流中读取

本文只会介绍新式的 API, 老式的方法已不推荐使用. 要在代码中使用 JsonCpp 库, 需要先包含头文件

#include "json/json.h"

以下是一段示例代码

Json::Value root;
std::ifstream ifs;
ifs.open("./example.json");

Json::CharReaderBuilder builder;
JSONCPP_STRING errs;
Json::parseFromStream(builder, ifs, &root, &errs);
cout << root;

JsonCpp 包含命名空间 Json, 类 Value 表示 Json 对象. 代码中第 1 行是在新建一个 Json 对象

CharReaderBuilder 用于创建一个 读取器 (第 5 行代码的工作)

JSONCPP_STRING 是一个 typedef, 表示 Json::String 对象, 是 JsonCpp 中用于存储字符串的类型, 类似于标准的 std::string 类型

parseFromStream() 方法可以从文件流中读取 Json 数据, 它的函数原型如下:

bool Json::parseFromStream (
        CharReader::Factory const & fact,
        IStream & sin,
        Value * root,
        String * errs 
) 	

需要注意的是, parseFromStream() 方法的第一个参数类型是 CharReader::Factory const &, 而我们构建的读取器 builder 的类型是 CharReaderBuilder. 这其实是因为 CharReaderBuilder 类是继承自 CharReader::Factory

JsonCpp 重载了 std::cout 方法, 可以直接使用 cout 方法打印 Json 数据 (第 8 行的工作)

修改 Json 数据

从流中读取 Json 文件后, 可以直接使用数组索引的方式修改 Json 数据

假设有如下 Json 文件:

{
    "name": "Fie",
    "gender": "Female",
    "weapon": "Dagger",
    "master": {
        "name": "Sara Valestein",
        "gender": "Female",
        "occupation": "Instructor",
        "affiliation": "Thors Military Academy",
        "weapon": "Sword"
    },
    "class": "Class VII",
    "likes": [
        "Napping",
        "Snacking",
        "Observing surroundings",
        "Practicing swordsmanship",
        "Going on missions with friends"
    ]
}

我们希望修改 class 的值为 Class VIII, 可以直接使用

root["class"] = "Class VIII";

修改数组, 直接使用位置索引即可, 因为数组是有序的, 索引从 0 开始:

root["likes"][1] = "Snacking ^_^";

修改嵌套的 Json 对象与修改二维数组类似:

root["master"]["weapon"] = "Sword >_<";

修改之后的 Json 数据如下:

{
    "class" : "Class VIII",
    "gender" : "Female",
    "likes" :
    [
            "Napping",
            "Snacking ^_^",
            "Observing surroundings",
            "Practicing swordsmanship",
            "Going on missions with friends"
    ],
    "master" :
    {
            "affiliation" : "Thors Military Academy",
            "gender" : "Female",
            "name" : "Sara Valestein",
            "occupation" : "Instructor",
            "weapon" : "Sword >_<"
    },
    "name" : "Fie",
    "weapon" : "Dagger"
}

如果要修改的内容在 Json 中不存在, 则会变成插入

写入文件

假设要将修改后的数据写入 example_new.json 文件中, 示例如下

std::ofstream ofs;
ofs.open("./example_new.json");

Json::StreamWriterBuilder wbuilder;
const std::unique_ptr<Json::StreamWriter> writer(wbuilder.newStreamWriter());
writer->write(root, &ofs);

同样的, 需要新建一个 写入器 wbuilder, 它是 StreamWriterBuilder 类型的. 使用这个写入器去初始化一个智能指针 writer, 它是 StreamWriter 类型的, 而方法 newStreamWriter() 会返回一个 StreamWriter 类型的指针

之后使用 write() 方法将数据写回输出流即可

其他

授人以鱼不如授人以渔

JsonCpp 仓库链接: 这里

JsonCpp 文档链接: 这里

JsonCpp 官方是提供了代码示例的, 在仓库的 ./example 目录下, 包括从文件流读写和从代码的 string 对象读写:

  • readFromStream
  • readFromString
  • streamWrite
  • stringWrite

JsonCpp 代码示例: 这里

标签:数组,gender,读写,JsonCpp,Json,jsoncpp,Female
From: https://www.cnblogs.com/asnelin/p/18117570

相关文章

  • 【Java】轻量Excel读写框架学习
     参考黑马教程:https://www.bilibili.com/video/BV1eA41157va?p=5写着写着发现有更好的Demo案例:https://cloud.tencent.com/developer/article/1966065所需依赖:<dependency><groupId>org.apache.tika</groupId><artifactId>tika-core</artifa......
  • tsconfig.build.json 和 tsconfig.json 的区别是什么,为啥分为两个?
    tsconfig.json和tsconfig.build.json都是TypeScript编译器的配置文件,它们用于定义TypeScript项目的编译选项和规则。虽然它们的核心功能相同,但通常情况下,项目中会有多个tsconfig文件,如tsconfig.build.json,以满足不同编译场景的需求。下面是它们之间的一些关键区别:目......
  • Java -fastjson api
    构造json对象需求:构造以下请求体{"attrSelectionVO":[{"attrAccessId":"eea99a0894504a2b89f3cfeb4be051d3","attrValueList":[{"attrValue":"输送型","att......
  • docker 配置文件 deamon.json
    {"allow-nondistributable-artifacts":[],"api-cors-header":"","authorization-plugins":[],"bip":"","bridge":"","builder":{"gc":{&......
  • ShardingJDBC-5.3实现读写分离,构建主从MySQL数据库,Docker部署Mysql8.0
      最近在做一个项目需要搭建MySQL主从架构,采用ShardingJDBC5.3实现MySQL读写分离,本文记录一下搭建流程。基于Docker创建主从架构#创建主从数据库文件夹mkdir-p/usr/local/mysql/master1/confmkdir-p/usr/local/mysql/master1/datamkdir-p/usr/local/mysql/s......
  • 数据库读写分离(主从复制)和分库分表详解
    数据库读写分离(主从复制)和分库分表在文章开头先抛几个问题:什么是读写分离?解决了什么问题?使用时应该注意什么?会出现什么问题?什么是主从复制?他有什么缺点?我们为什么要分库分表?什么时候才需要分库分表呢?我们的评判标准是什么?这些问题你都搞清楚了吗?相信看完这篇文章你一定......
  • python 解析json字符串保存到对象中
    在Python中,你可以使用内置的json模块来解析JSON字符串并保存到对象中。以下是一个简单的示例:pythonimportjson#假设你有以下的JSON字符串json_string='{"name":"Alice","age":25,"city":"NewYork"}'#使用json模块的loads方法将JSON字符串解析为Python对象(在这种情况下......
  • 如何根据JSON文件内容生成自定义对象
    在Python中,你可以使用json模块来解析JSON文件,并将解析后的数据映射到自定义的Python对象上。这通常涉及到定义一个类,并为该类实现一个__init__方法来初始化对象的属性。然后,你可以编写一个函数来读取JSON文件,将解析后的数据传递给类的构造函数,从而创建自定义对象。下面是一个简单......
  • Python中处理JSON字段时,和如何将Python对象转换为JSON字符串
    在Python中处理JSON字段时,通常使用内置的json模块。这个模块允许你将Python对象转换为JSON字符串,以及将JSON字符串解析为Python对象。以下是一些常见的JSON字段处理操作:1.将Python对象转换为JSON字符串python复制importjson#定义一个Python字典data={  "name"......
  • 使用NodeJS将数据保存成JSON文件
    使用NodeJS将数据保存成JSON文件 在平时我需要把后端一些object变量保存至本地,可以这样做:constexpress=require("express");constapp=express();constserver=require("http").createServer(app);constfs=require('fs');app.use(express.static("publ......