希望我们不仅把编程当成一份工作,更要将其当成一份热爱!!!
-----潜意识中有个想成为一名厉害的程序员的梦
1.Jsoncpp环境配置(我用的vs2019,其他版本也同理)
- 此网址下载其压缩包,解压(GitHub - open-source-parsers/jsoncpp: A C++ library for interacting with JSON.)(若网址加载缓慢或打不开,可采用Watt Toolkit加速器(百度安装即可)、或者科学上网)
- 将图1、图2 的这两个路径的文件,拷贝到你的项目文件中,可以在你的项目文件中新建一个文件,我这里新建了json文件夹(图3)
![]() | ![]() |
---|---|
图1 | 图2 |
![]() |
---|
图3 |
- 在你的工程中新建文件夹json,并把上面拷贝的文件全部加入
![]() |
---|
- 包含 你上述(图3)建的文件夹的路径:
![]() |
---|
- 编译后 会出现头文件的报错,把报错的头文件中 json/ 去掉 就好了。
2.Jsoncpp的使用示例
- 新建.text文档,文本内容如下,编码格式为UTF-8.
{ “name”:“张三”, “age”:18, “身高”:1.81, “生日”:“2002-01-02”, “学校”:“北大青鸟”, “专业”:[“厨师”,“挖掘机”], “单身”:true, “地址”:null } | ![]() |
---|
- 程序源码如下(此代码,存在一点问题,若想直接用正确的请跳到文章末尾。不过跟着我的步骤来,有利于你更加清晰关于编码的问题)
#include <iostream>
#include <fstream>
#include <json.h>
int main() {
//替换为你的json文件的路径
std::string path = "C:\\Users\\Hanxiangqian\\Desktop\\秋招\\项目\\tools_study\\tool_study\\json.txt";
// 打开 JSON 文件
std::ifstream file(path,std::ifstream::binary);
if (!file.is_open()) {
std::cerr << "无法打开文件 data.json" << std::endl;
return 1;
}
// 创建 JSON 解析器
Json::CharReaderBuilder readerBuilder;
Json::Value root;
std::string errs;
// 读取并解析 JSON 文件
if (!Json::parseFromStream(readerBuilder, file, &root, &errs)) {
std::cerr << "解析 JSON 文件失败: " << errs << std::endl;
return 1;
}
// 关闭文件
file.close();
// 访问 JSON 数据
std::string name = root["name"].asString();
int age = root["age"].asInt();
double height = root["身高"].asDouble();
std::string birthday = root["生日"].asString();
std::string school = root["学校"].asString();
const Json::Value majors = root["专业"];
bool single = root["单身"].asBool();
Json::Value address = root["地址"];
// 输出 JSON 数据
std::cout << "Name: " << name << std::endl;
std::cout << "Age: " << age << std::endl;
std::cout << "Height: " << height << std::endl;
std::cout << "Birthday: " << birthday << std::endl;
std::cout << "School: " << school << std::endl;
std::cout << "Majors: ";
for (const auto& major : majors) {
std::cout << major.asString() << " ";
}
std::cout << std::endl;
std::cout << "Single: " << (single ? "true" : "false") << std::endl;
std::cout << "Address: " << (address.isNull() ? "null" : address.asString()) << std::endl;
return 0;
}
- 运行结果如下:
![]() | ![]() |
---|
3.乱码及其编码问题解决
1.代码开头 设置控制台的编码方式为 UTF-8,
// 设置控制台输出为 UTF-8 编码
SetConsoleOutputCP(CP_UTF8);
2.关于中文的键的字符串 前加u8
double height = root[u8"身高"].asDouble();
std::string birthday = root[u8"生日"].asString();
std::string school = root[u8"学校"].asString();
const Json::Value majors = root[u8"专业"];
bool single = root[u8"单身"].asBool();
Json::Value address = root[u8"地址"];
3.运行结果如下:正确
![]() | ![]() |
---|
1.首先json.txt的文本是以UTF-8的编码方式,被编码为二进制的字节流(所有文件都是以二进制形式进行存储的)存储的。
2.我们在读取文件的时候,实际上读取的也是二进制流。在控制台进行显示的时候,会先对其二进制流进行编码,编码成相应的字符后进行显示,所以如果控制台的编码方式(控制台编码默认为GBK)非utf-8,就会出现乱码的情况。因此设置控制台输出为 UTF-8 编码,以使文本被正常显示。
3.以这行代码举例 double height = root[“身高”].asDouble(); 本来我们是想通过找到 “身高” 这个键来找到 “1.81” 这个数据的。但计算机底层是通过二进制数据来对比键的,这里身高是按照GBK来进行编码的,其对应的二进制是:C9 ED B8 DF。而我们的文档是按照UTF-8 进行编码的,所以文档中 “身高” 对应的二进制是:E8 BA AB E9 AB 98。
字符 | root["身高"]:GBK 编码(这里是采用系统的编码方式) | json文件:UTF-8 编码 |
---|---|---|
身高 | C9 ED B8 DF | E8 BA AB E9 AB 98 |
当我们指定字符串的编码方式为utf-8后:double height = root[u8"身高"].asDouble();
字符 | root["u8身高"]:UTF-8编码 | json文件:UTF-8 编码 |
---|---|---|
身高 | E8 BA AB E9 AB 98 | E8 BA AB E9 AB 98 |
此时 通过 E8 BA AB E9 AB 98 来找键,就能找到了。
4.正确的完整版代码如下
#include <iostream>
#include <fstream>
#include <json.h>
#include <Windows.h> // 用于设置控制台编码
int main() {
// 设置控制台输出为 UTF-8 编码
SetConsoleOutputCP(CP_UTF8);
std::string path = "C:\\Users\\Hanxiangqian\\Desktop\\秋招\\项目\\tools_study\\tool_study\\json.txt";
// 打开 JSON 文件
std::ifstream file(path,std::ifstream::binary);
if (!file.is_open()) {
std::cerr << "无法打开文件 data.json" << std::endl;
return 1;
}
// 创建 JSON 解析器
Json::CharReaderBuilder readerBuilder;
Json::Value root;
std::string errs;
// 读取并解析 JSON 文件
if (!Json::parseFromStream(readerBuilder, file, &root, &errs)) {
std::cerr << "解析 JSON 文件失败: " << errs << std::endl;
return 1;
}
// 关闭文件
file.close();
// 访问 JSON 数据
std::string name = root["name"].asString();
int age = root["age"].asInt();
double height = root[u8"身高"].asDouble();
std::string birthday = root[u8"生日"].asString();
std::string school = root[u8"学校"].asString();
const Json::Value majors = root[u8"专业"];
bool single = root[u8"单身"].asBool();
Json::Value address = root[u8"地址"];
// 输出 JSON 数据
std::cout << "Name: " << name << std::endl;
std::cout << "Age: " << age << std::endl;
std::cout << "Height: " << height << std::endl;
std::cout << "Birthday: " << birthday << std::endl;
std::cout << "School: " << school << std::endl;
std::cout << "Majors: ";
for (const auto& major : majors) {
std::cout << major.asString() << " ";
}
std::cout << std::endl;
std::cout << "Single: " << (single ? "true" : "false") << std::endl;
std::cout << "Address: " << (address.isNull() ? "null" : address.asString()) << std::endl;
return 0;
}