详细介绍如何使用rapidjson读取json文件
本文主要详细介绍如何使用rapidjson库来实现.json文件的读取,分为相关基础介绍、结合简单示例进行基础介绍、结合复杂示例进行详细的函数实现介绍等三部分。
一、相关基础
1、Json文件中的{}
和 []
在 JSON 文件中,{}
和 []
分别表示不同的数据结构:
(1) {}
表示对象(Object)
- 语义:
{}
表示键值对的集合。 - 结构:每个键是一个字符串,键与值之间用冒号(
:
)分隔,键值对之间用逗号(,
)分隔。 - 特点:
- 键是唯一的,值可以是任意类型(如字符串、数字、布尔值、数组、对象等)。
- 对象类似于 C++ 中的
std::map
或 Python 中的字典(dict
)。
示例:
{"name": "John", "age": 30, "married": true
}
- 解析:
name
是键,值为字符串"John"
。age
是键,值为整数30
。married
是键,值为布尔值true
。
(2) []
表示数组(Array)
- 语义:
[]
表示有序的值列表。 - 结构:值之间用逗号(
,
)分隔,值可以是任意类型(如字符串、数字、布尔值、数组、对象等)。 - 特点:
- 数组中的值没有键,只有索引(从 0 开始)。
- 数组类似于 C++ 中的
std::vector
或 Python 中的列表(list
)。
示例:
[10, 20, 30, 40]
- 解析:
- 数组包含 4 个整数值:
10
、20
、30
和40
。
- 数组包含 4 个整数值:
(3)综合示例
一个 JSON 文件可以同时包含对象和数组的嵌套:
{"person": {"name": "Alice","age": 25,"hobbies": ["reading", "cycling", "traveling"]},"scores": [85, 90, 78]
}
- 解析:
person
是一个对象,包含键值对:name
:"Alice"
(字符串)age
:25
(整数)hobbies
: 一个数组,包含 3 个字符串。
scores
是一个数组,包含 3 个整数。
(4)总结
{}
:用于表示对象(键值对的集合)。[]
:用于表示数组(有序值列表)。
2、常用函数
JSON 文件中常用的函数分类及详细列表如下所示,基于 RapidJSON 库进行了分类整理。
注:下面示例中的doc是用来存储解析后的JSON数据的主要对象,可通过rapidjson::Document doc
声明
(1) 文件处理相关
函数名 | 函数用途 | 使用示例 |
---|---|---|
ParseStream | 解析输入流中的 JSON 数据 | doc.ParseStream(isw); |
Parse | 解析字符串中的 JSON 数据 | doc.Parse(jsonStr.c_str()); |
HasParseError | 检查解析是否出错 | if (doc.HasParseError()) { /* 错误处理 */ } |
(2)解析与验证相关
函数名 | 函数用途 | 使用示例 |
---|---|---|
HasMember | 检查对象是否包含指定键 | if (doc.HasMember("key")) { /* 存在键 */ } |
IsObject | 检查 JSON 节点是否为对象 | if (doc["key"].IsObject()) { /* 是对象 */ } |
IsArray | 检查 JSON 节点是否为数组 | if (doc["key"].IsArray()) { /* 是数组 */ } |
IsString | 检查 JSON 节点是否为字符串 | if (doc["key"].IsString()) { /* 是字符串 */ } |
IsInt | 检查 JSON 节点是否为整数 | if (doc["key"].IsInt()) { /* 是整数 */ } |
IsDouble | 检查 JSON 节点是否为浮点数 | if (doc["key"].IsDouble()) { /* 是浮点数 */ } |
IsBool | 检查 JSON 节点是否为布尔值 | if (doc["key"].IsBool()) { /* 是布尔值 */ } |
IsNull | 检查 JSON 节点是否为空 | if (doc["key"].IsNull()) { /* 是空值 */ } |
函数名 | 函数用途 | 使用示例 |
---|---|---|
IsNumber | 检查 JSON 节点是否为数字(整数或浮点数) | if (doc["key"].IsNumber()) { /* 是数字 */ } |
IsUint | 检查 JSON 节点是否为无符号整数 | if (doc["key"].IsUint()) { /* 是无符号整数 */ } |
IsUint64 | 检查 JSON 节点是否为 64 位无符号整数 | if (doc["key"].IsUint64()) { /* 是64位无符号整数 */ } |
IsInt64 | 检查 JSON 节点是否为 64 位整数 | if (doc["key"].IsInt64()) { /* 是64位整数 */ } |
IsLosslessDouble | 检查浮点数是否能无损转换为整数 | if (doc["key"].IsLosslessDouble()) { /* 无损转换 */ } |
(3) 对象操作相关
函数名 | 函数用途 | 使用示例 |
---|---|---|
operator[] | 获取对象中指定键的值 | auto value = doc["key"]; |
MemberBegin | 获取对象的第一个键值对迭代器 | for (auto itr = obj.MemberBegin(); itr != obj.MemberEnd(); ++itr) { std::cout << itr->name.GetString(); } |
MemberEnd | 获取对象的最后一个键值对迭代器 | 同上 |
(4)数组操作相关
函数名 | 函数用途 | 使用示例 |
---|---|---|
operator[] | 获取数组中指定索引的值 | auto value = doc["key"][0]; |
Begin | 获取数组的第一个元素迭代器 | for (auto itr = array.Begin(); itr != array.End(); ++itr) { std::cout << itr->GetInt(); } |
End | 获取数组的最后一个元素迭代器 | 同上 |
Size | 获取数组大小 | size_t len = doc["key"].Size(); |
(5) 获取操作相关
函数名 | 函数用途 | 使用示例 |
---|---|---|
GetString | 获取字符串值 | std::string str = doc["key"].GetString(); |
GetInt | 获取整数值 | int val = doc["key"].GetInt(); |
GetDouble | 获取浮点数值(包括 float 类型) | double val = doc["key"].GetDouble(); |
GetBool | 获取布尔值 | bool flag = doc["key"].GetBool(); |
GetArray | 获取数组值(作为数组对象) | const auto& arr = doc["key"].GetArray(); |
GetObject | 获取对象值(作为对象) | const auto& obj = doc["key"].GetObject(); |
函数名 | 函数用途 | 使用示例 |
---|---|---|
GetUint | 获取无符号整数值 | unsigned int val = doc["key"].GetUint(); |
GetInt64 | 获取 64 位整数值 | int64_t val = doc["key"].GetInt64(); |
GetUint64 | 获取 64 位无符号整数值 | uint64_t val = doc["key"].GetUint64(); |
关于浮点数
-
基础的RapidJSON 中没有
GetFloat
函数。 -
浮点数统一通过
GetDouble
获取。即使是 JSON 文件中的浮点数值可以存储为单精度(float),也会被解释为双精度(double)。 -
若需要
float
类型的值,可以使用强制类型转换:float val = static_cast<float>(doc["key"].GetDouble());
-
即使在某些RapidJSON中,对
GetFloat
函数也进行了封装,比如我使用的这个版本的document.h文件中,进行了以下封装,所以也可以直接用GetFloat
函数。但其本质还是通过GetDouble
函数获取,然后进行类型转换后返回的。
[[_resources/详细介绍如何使用rapidjson读取json文件/bc2fcd9db0921f81d29d3018268dc70e_MD5.jpeg|Open: Pasted image 20241206092810.png]]
![[_resources/详细介绍如何使用rapidjson读取json文件/bc2fcd9db0921f81d29d3018268dc70e_MD5.jpeg]]
float GetFloat() const {return static_cast<float>(GetDouble());
}
综合示例
示例JSON文件如下:
{"Info": {"author": "JZX-MY","number": 7,},"regions": [{"name": "Area 1","points": [{"x": 1.0,"y": 2.0},{"x": 3.0,"y": 4.0}]},{"name": "Area 2","points": [{"x": 5.0,"y": 6.0},{"x": 7.0,"y": 8.0}]}]
}
读取该示例JSON文件的代码片段如下:
#include <iostream>
#include <rapidjson/document.h>
#include <rapidjson/istreamwrapper.h>
#include <fstream>int main() {// 读取 JSON 文件std::ifstream ifs("data.json");rapidjson::IStreamWrapper isw(ifs);// 解析 JSON 文件rapidjson::Document doc;doc.ParseStream(isw);// 检查是否存在错误if (doc.HasParseError()) {std::cerr << "解析失败!" << std::endl;return -1;}// 获取对象中的值std::string author = doc["Info"]["author"].GetString();int number = doc["Info"]["number"].GetInt();// 遍历数组const auto& regions = doc["regions"].GetArray();for (const auto& region : regions) {std::cout << "Region Name: " << region["name"].GetString() << std::endl;const auto& points = region["points"].GetArray();for (const auto& point : points) {std::cout << " Point: (" << point["x"].GetDouble() << ", " << point["y"].GetDouble() << ")" << std::endl;}}return 0;
}
二、结合简单示例进行详细的基础介绍
0. 示例
本部分内容以读取如下所示非常简单的test.json文件为例
{
"points": [-17, -15, 0],
"cost": 10,
"rate": 0.6,
}
对应的读取示例程序如下:
bool readJson(std::string& file_path, int& cost, double& occ_th, double& free_th) {std::string read_path = file_path + "/test.json";std::cout << "Read Json: " << read_path << std::endl;// 加载 JSON 文件std::ifstream ifs(read_path);if (!ifs.is_open()) {std::cout << " could not open " << read_path << std::endl;return false;}rapidjson::IStreamWrapper isw(ifs);rapidjson::Document doc;doc.ParseStream(isw);if (doc.HasParseError()) {std::cerr << "Error JSON file " << read_path << std::endl;return false;}// 解析 points 数组if (doc.HasMember("points") && doc["points"].IsArray() && doc["points"].Size() == 3) {points_.x() = doc["points"][0].GetDouble();points_.y() = doc["points"][1].GetDouble();std::cout << "points x: " << points_.x() << " points y: " << points_.y()<< " points th: " << doc["points"][2].GetDouble() << std::endl;} else {std::cerr << "Invalid points data in map_.json" << std::endl;return false;}// 读取 costif (doc.HasMember("cost") && doc["cost"].IsInt()) {cost = doc["cost"].GetInt();std::cout << "cost: " << cost << std::endl;} else {std::cerr << "The JSON does not contain a cost tag or it is invalid." << std::endl;return false;}// 读取 rateif (doc.HasMember("rate") && doc["rate"].IsDouble()) {occ_th = doc["rate"].GetDouble();std::cout << "rate: " << occ_th << std::endl;} else {std::cerr << "The JSON does not contain an rate tag or it is invalid." << std::endl;return false;}return true;
}
在上述代码中,函数 readJson
使用了 RapidJSON 读取和解析一个 JSON 文件。以下是分步骤的详细介绍,以及如何正确使用 RapidJSON 读取 JSON 文件并提取数据:
1. 准备工作
- 路径声明:std::string read_path = file_path + “/test.json”;
- 定义要解析的 JSON 文件路径。
示例如下:
std::string read_path = file_path + "/test.json";
std::cout << "Read Json: " << read_path << std::endl;
- 加载文件:通过
std::ifstream
打开文件流,确保文件可用。- 如果文件无法打开,返回错误。
示例如下:
std::ifstream ifs(read_path);
if (!ifs.is_open()) {std::cout << "test.json could not open " << read_path << std::endl;return false;
}
2. 创建 RapidJSON 的流包装器
RapidJSON 使用 IStreamWrapper
将标准的 C++ 输入流包装为可供 RapidJSON 解析的流。
rapidjson::IStreamWrapper isw(ifs);
- 文档对象:
rapidjson::Document doc
是用来存储解析后 JSON 数据的主要对象。 - 解析 JSON 流:通过
doc.ParseStream(isw)
解析 JSON 文件内容。
rapidjson::Document doc;
doc.ParseStream(isw);
if (doc.HasParseError()) {std::cerr << "Error JSON file " << read_path << std::endl;return false;
}
3. 验证和提取 JSON 数据
(1)验证 JSON 数据 【非必要】
- 可以使用
doc.HasParseError()
检查 JSON 文件的解析是否出错。 - 对每个 JSON 字段,使用
doc.HasMember("key")
检查该字段是否存在,并验证字段类型,例如IsArray()
、IsDouble()
等。
(2)解析 JSON 字段
{
"points": [-17, -15, 0],
"cost": 10,
"rate": 0.6,
}
数组字段解析示例——points
字段解析
已知points
是一个含有3个数字的数组字段,这里代码验证json文件中是否含有points
成员、它是否为数组,长度是否为 3,若验证成功,则提取数据,并保存至合适的变量中(示例中保存到了类内变量中)。
对于名为points
的数组字段,且数据类型为double,可以使用 doc[ "points" ][ 0 ].GetDouble();
来读取其第一个元素,以此类推
if (doc.HasMember("points") && doc["points"].IsArray() && doc["points"].Size() == 3) {points_.x() = doc["points"][0].GetDouble();points_.y() = doc["points"][1].GetDouble();std::cout << "points x: " << points_.x() << " points y: " << points_.y()<< " points th: " << doc["points"][2].GetDouble() << std::endl;
} else {std::cerr << "Invalid points data in map_.json" << std::endl;return false;
}
整数字段解析示例——cost
字段解析
cost
是一个整数字段,代码doc.HasMember(“cost”) 验证是否含有成员cost, 使用 IsInt()
验证其类型是否为int,并通过 GetInt()
获取值。
if (doc.HasMember("cost") && doc["cost"].IsInt()) {cost = doc["cost"].GetInt();std::cout << "cost: " << cost << std::endl;
} else {std::cerr << "The JSON does not contain a cost tag or it is invalid." << std::endl;return false;
}
浮点数字段解析示例——rate
字段解析
rate
是一个浮点数字段,代码使用 IsDouble()
验证类型,并通过 GetDouble()
获取值。
if (doc.HasMember("rate") && doc["rate"].IsDouble()) {occ_th = doc["rate"].GetDouble();std::cout << "rate: " << occ_th << std::endl;
} else {std::cerr << "The JSON does not contain an rate tag or it is invalid." << std::endl;return false;
}
4. 返回解析结果
在所有字段都成功解析后,函数返回 true
,否则返回 false
。
5. 总结 RapidJSON 的使用
- 文件读取:通过
std::ifstream
和rapidjson::IStreamWrapper
将文件内容传递给 RapidJSON。 - 文档解析:通过
rapidjson::Document
和ParseStream
将 JSON 数据加载到内存中。 - 字段验证:使用
HasMember
和字段类型检查确保数据完整性。 - 字段提取:通过
Get<Type>()
函数提取具体数据。
这种方法适用于处理结构明确的 JSON 文件,提供高效且安全的解析能力。
三、结合复杂示例进行详细的函数实现介绍
本部分以如下所示的示例为例子展开介绍
{"Info": {"author": "JZX_MY","version": "v1.0.96","number": 66,"position": [-9, 60.0, 10.0],"rate": 0.99},"scale": 77,"regions": [{"index": 0,"name": "free_regions","points": [{"x": -2.03,"y": 2.25},{"x": 1.39,"y": 5.82},{"x": 7.47,"y": 2.35},{"x": 5.50,"y": -1.36}]},{"index": 1,"name": "occupy_regions","points": [{"x": -2.03,"y": 27.25},{"x": 10.39,"y": 5.82},{"x": 78.47,"y": 2.35}]}],"param": {"max_threshold": 0.05,"max_num" : 10240,"success" : true},"robot": {"width": 1510,"length": 5180,"radius": 3420},"other": []
}
1、编写通用的基本读取框架
根据第二部分的介绍,我们先编写读取一个JSON所需的一些基本框架,如下所示,
/*** 使用rapidJSON解析JSON文件的函数* @param directory_path 文件所在的目录路径* @param file_name 文件名*/
bool readJSON(const std::string& directory_path, const std::string& file_name) {// (1)拼接完整的文件路径std::string full_file_path = directory_path + "/" + file_name;std::cout << "Read Json file: " << full_file_path << std::endl;// (2)打开JSON文件流std::ifstream ifs(full_file_path);if (!ifs.is_open()) {// 如果文件无法打开,输出错误信息并返回std::cerr << "could not open: " << full_file_path << std::endl;return false;}// (3)使用rapidJSON的IStreamWrapper包装文件流,方便解析rapidjson::IStreamWrapper isw(ifs);// (4)定义rapidJSON的Document对象,用于存储解析后的JSON数据rapidjson::Document doc;doc.ParseStream(isw);// (5)检查JSON文件解析是否成功if (doc.HasParseError()) {// 如果解析失败,输出错误信息并返回std::cerr << "Error JSON file!" << std::endl;return false;}// ------------------------开始读取------------------------------// 开始逐个解析读取JSON字段 [后面的步骤补充]..................// ------------------------读取完成------------------------------// 关闭文件流ifs.close();return true;
}
其详细介绍如下:
(1)为了方便对多个类似结构的文件进行读取,下面的示例采用了将文件所在路径directory_path和文件名file_name以形参传入的方式,将其拼接后得到完整的要读取的JSON文件的路径full_file_path
// (1)拼接完整的文件路径
std::string full_file_path = directory_path + "/" + file_name;
std::cout << "Read Json file: " << full_file_path << std::endl;
(2)使用std::ifstream(输入文件流)创建一个文件流对象ifs。传入full_file_path作为参数,表示要打开的文件路径。std::ifstream会尝试打开指定路径的文件,并准备从文件中读取数据。【注:文件路径需要是完整路径,只有当路径正确且文件存在时,文件才能成功打开,没有指定模式时,默认以只读模式打开文件(std::ios::in)】
// (2)打开JSON文件流
std::ifstream ifs(full_file_path);
if (!ifs.is_open()) {// 如果文件无法打开,输出错误信息并返回std::cerr << "could not open: " << full_file_path << std::endl;return false;
}
(3)使用RapidJSON 的IStreamWrapper
将标准的 C++ 输入流对象ifs包装为可供 RapidJSON 解析的流isw。
// (3)使用rapidJSON的IStreamWrapper包装文件流,方便解析
rapidjson::IStreamWrapper isw(ifs);
(4)定义rapidJSON的Document对象doc,用于存储解析后的JSON数据文档对象,然后通过 doc.ParseStream(isw)
解析 JSON 文件内容。
// (4)定义rapidJSON的Document对象,用于存储解析后的JSON数据
rapidjson::Document doc;
doc.ParseStream(isw);
(5)检查JSON文件解析是否成功
// (5)检查JSON文件解析是否成功
if (doc.HasParseError()) {// 如果解析失败,输出错误信息并返回std::cerr << "Error JSON file!" << std::endl;return false;
}
(6)若解析成功,则开始根据JSON文件的结构内容,依次进行读取【在下一节中介绍】
(7)成功读取完成后,关闭C++文件流ifs,并返回true
到这里读取一个JSON文件的常用框架就介绍完了,下面根据示例JSON文件的结构补充读取部分
2、在通用框架的基础上补充实际要读取的内容
(1)示例中的Info部分
首先回顾第一部分中的内容:{}
是对象,表示键值对的集合。每个键是一个字符串,键与值之间用冒号(:
)分隔,键值对之间用逗号(,
)分隔。键是唯一的,值可以是任意类型(如字符串、数字、布尔值、数组、对象等)。[]
是数组,表示有序的值列表。值之间用逗号(,
)分隔,值可以是任意类型(如字符串、数字、布尔值、数组、对象等)。 数组中的值没有键,只有索引(从 0 开始)。对象和数组可以互相嵌套,产生一些比较复杂的结构
本部分内容的结构相对简单,Info作为总的JSON文件对象的一个键值对中的键,值是一个对象,该对象中又包含了author、version、number、position、rate这五个键值对,除了position之外,其他键值对的值都是单个数据,position的值又是一个数组,数组中每个元素也都是普通的单个数据,没有再嵌套下去。
{"Info": {"author": "JZX_MY","version": "v1.0.96","number": 66,"position": [-9, 60.0, 10.0],"rate": 0.99}
}
我们先来看Info对象的第一个键值对"author": “JZX_MY”,常见的读取方式有以下三种
第一种:通过最简化的直接链式访问
可以直接通过链式访问来读取,如下所示,根据第一部分中常用函数的介绍,读取字符串类型用GetString()函数即可
std::string author = doc["Info"]["author"].GetString();
std::cout << "Author: " << author << std::endl;
在确定 JSON 的结构是固定的,并且不会缺少任何字段的情况下,可以直接使用类似于 doc["Info"]["author"]
的链式访问方式,代码更简洁。缺点是,如果 Info 不存在、不是对象,或者 author 不存在、不是字符串,则会导致程序崩溃。
第二种:通过分层安全访问
这种方式的核心是进行逐步检查,确保每一步的操作都符合预期的条件,然后再执行具体的逻辑。不会因为 JSON 结构问题导致程序崩溃。 能够在异常情况(例如字段缺失或类型不匹配)时,自定义处理逻辑(如打印错误信息)。但代码更长,显得繁琐。如下所示:
// 检查 JSON 对象是否包含名为 "Info" 的成员,并且该成员是一个对象
if (doc.HasMember("Info") && doc["Info"].IsObject()) {// 获取 "Info" 成员,并存储为一个常量引用const rapidjson::Value& info = doc["Info"];// 检查 "Info" 对象是否包含名为 "author" 的成员,并且该成员是一个字符串if (info.HasMember("author") && info["author"].IsString()) {// 获取 "author" 成员的字符串值,并存储到变量 author 中std::string author = info["author"].GetString();// 输出 "author" 的值到控制台std::cout << "Author: " << author << std::endl;}
}
第三种:通过链式安全访问
可以将前两种结合一下,先检查,然后再通过链式访问,省去了临时中间变量’const rapidjson::Value& info = doc[“Info”];’
// 检查 JSON 对象是否包含名为 "Info" 的成员,并且该成员是一个对象
if (doc.HasMember("Info") && doc["Info"].IsObject()) {// 直接链式访问检查 "Info" 对象中的 "author" 成员if (doc["Info"].HasMember("author") && doc["Info"]["author"].IsString()) {// 直接链式获取 "author" 的字符串值std::string author = doc["Info"]["author"].GetString();// 输出 "author" 的值到控制台std::cout << "Author: " << author << std::endl;}
}
该方式虽然看起来稍微简洁了一些,但是 每次链式访问都会重新解析路径,因此可能会稍微影响性能,尤其在大规模或复杂 JSON 时。使用临时中间变量(如 info
)会在逻辑上缓存某个子节点的引用,从而提高性能。如果后续多次访问 "Info"
的内容,建议保留 const rapidjson::Value& info
方式以减少重复解析。【即第二种方式】
综合来看,第二种分层安全访问的方式是最值得推荐的,version、number、rate项与author项类似(换成对应类型的函数即可),这里就不展开介绍了,我们再来看一下position项,给出带检查与不带检查的写法示例
第一种:通过最简化的直接链式访问
如果完全确定数据结构正确,并希望最简化代码,可以直接链式访问:
float x = doc["Info"]["position"][0].GetFloat();
float y = doc["Info"]["position"][1].GetFloat();
float z = doc["Info"]["position"][2].GetFloat();
std::cout << "Position: (" << x << ", " << y << ", " << z << ")" << std::endl;
缺点:
- 缺乏安全性检查,一旦 JSON 数据结构有误(例如
position
缺失、不是数组或者长度不足),会导致程序崩溃。
第二种:通过分层安全访问
这种方法逐层检查 JSON 的结构,确保安全性:
if (doc.HasMember("Info") && doc["Info"].IsObject()) {const rapidjson::Value& info = doc["Info"]; // 获取 "Info" 对象if (info.HasMember("position") && info["position"].IsArray()) {const rapidjson::Value& position = info["position"]; // 获取 "position" 数组// 检查数组长度并逐个读取元素if (position.Size() == 3) { // 假设数组有3个元素float x = position[0].GetFloat(); // 获取第一个元素float y = position[1].GetFloat(); // 获取第二个元素float z = position[2].GetFloat(); // 获取第三个元素// 输出读取结果std::cout << "Position: (" << x << ", " << y << ", " << z << ")" << std::endl;} else {std::cerr << "Position array size is not 3!" << std::endl;}} else {std::cerr << "Position does not exist or is not an array!" << std::endl;}
}
优点:
- 每一步都进行了显式检查,适用于不确定 JSON 数据结构是否完全符合预期的情况。
- 对数组的操作更清晰,容易扩展到更复杂的逻辑。
带检查的Info部分读取示例(仅打印未存储):
// 解析Info部分
if (document.HasMember("Info")) { // 检查是否包含"Info"字段const rapidjson::Value& info = doc["Info"];if (info.IsObject()) { // 确保"Info"是一个对象std::cout << "Info 部分解析结果:" << std::endl;if (info.HasMember("author") && info["author"].IsString()) {std::cout << "作者: " << info["author"].GetString() << std::endl; // 输出作者名称}if (info.HasMember("version") && info["version"].IsString()) {std::cout << "版本: " << info["version"].GetString() << std::endl; // 输出版本号}if (info.HasMember("number") && info["number"].IsInt()) {std::cout << "编号: " << info["number"].GetInt() << std::endl; // 输出编号}if (info.HasMember("position") && info["position"].IsArray()) {std::cout << "位置: ";for (auto& pos : info["position"].GetArray()) {std::cout << pos.GetFloat() << " "; // 输出位置坐标}std::cout << std::endl;}if (info.HasMember("rate") && info["rate"].IsDouble()) {std::cout << "速率: " << info["rate"].GetDouble() << std::endl; // 输出速率}}
}
(2)示例中的scale部分
本部分结构很简单,scale作为总的JSON文件对象的一个键值对中的键,值是一个普通的单个数据,没有嵌套。
{"scale": 77
}
直接访问:
int scale = doc["scale"].GetInt();
std::cout << "Scale: " << scale << std::endl;
安全的访问:
if (doc.HasMember("scale") && doc["scale"].IsInt()) {int scale = doc["scale"].GetInt(); // 读取 "scale" 的值std::cout << "Scale: " << scale << std::endl; // 输出结果
} else {std::cerr << "Scale is not present or not an integer!" << std::endl;
}
(3)示例中的regions部分
本部分结构相对复杂一点,regions作为总的JSON文件对象的一个键值对中的键,值是一个数组,数组中每个成员又是一个对象,该对象中含有index、name、points三个成员,其中points的值又是一个数组,数组中每个成员又是一个对象,该对象包含x和y两个键值对,值为普通变量,嵌套结束。
{"regions": [{"index": 0,"name": "free_regions","points": [{"x": -2.03,"y": 2.25},{"x": 1.39,"y": 5.82},{"x": 7.47,"y": 2.35},{"x": 5.50,"y": -1.36}]},{"index": 1,"name": "occupy_regions","points": [{"x": -2.03,"y": 27.25},{"x": 10.39,"y": 5.82},{"x": 78.47,"y": 2.35}]}]
}
第一种:最简洁的无检查写法
// 遍历regions数组中每个region
for (const auto& region : doc["regions"].GetArray()) {std::cout << "Region index: " << region["index"].GetInt() << std::endl;std::cout << "Region name: " << region["name"].GetString() << std::endl;// 遍历points数组中每个pointfor (const auto& point : region["points"].GetArray()) {std::cout << " Point: (x: " << point["x"].GetDouble()<< ", y: " << point["y"].GetDouble() << ")" << std::endl;}
}
第二种:逐层检查的最安全的写法
if (doc.HasMember("regions") && doc["regions"].IsArray()) {const rapidjson::Value& regions = doc["regions"];for (rapidjson::SizeType i = 0; i < regions.Size(); ++i) {const rapidjson::Value& region = regions[i];if (region.HasMember("index") && region["index"].IsInt()) {int index = region["index"].GetInt();std::cout << "Region index: " << index << std::endl;}if (region.HasMember("name") && region["name"].IsString()) {std::string name = region["name"].GetString();std::cout << "Region name: " << name << std::endl;}if (region.HasMember("points") && region["points"].IsArray()) {const rapidjson::Value& points = region["points"];for (rapidjson::SizeType j = 0; j < points.Size(); ++j) {const rapidjson::Value& point = points[j];if (point.HasMember("x") && point["x"].IsDouble() &&point.HasMember("y") && point["y"].IsDouble()) {double x = point["x"].GetDouble();double y = point["y"].GetDouble();std::cout << " Point: (x: " << x << ", y: " << y << ")" << std::endl;}}}}
}
第三种:仅针对顶层结构检查的的写法
if (doc.HasMember("regions") && doc["regions"].IsArray()) {for (const auto& region : doc["regions"].GetArray()) {int index = region["index"].GetInt();std::cout << "Region index: " << index << std::endl;std::string name = region["name"].GetString();std::cout << "Region name: " << name << std::endl;for (const auto& point : region["points"].GetArray()) {double x = point["x"].GetDouble();double y = point["y"].GetDouble();std::cout << " Point: (x: " << x << ", y: " << y << ")" << std::endl;}}
}
(4)示例中的param部分
{"param": {"max_threshold": 0.05,"max_num" : 10240,"success" : true}
}
第一种:无检查写法
const rapidjson::Value& param = doc["param"];
double max_threshold = param["max_threshold"].GetDouble();
int max_num = param["max_num"].GetInt();
bool success = param["success"].GetBool();std::cout << "Max Threshold: " << max_threshold << std::endl;
std::cout << "Max Num: " << max_num << std::endl;
std::cout << "Success: " << (success ? "true" : "false") << std::endl;
或
double max_threshold = doc["param"]["max_threshold"].GetDouble();
int max_num = doc["param"]["max_num"].GetInt();
bool success = doc["param"]["success"].GetBool();std::cout << "Max Threshold: " << max_threshold << std::endl;
std::cout << "Max Num: " << max_num << std::endl;
std::cout << "Success: " << (success ? "true" : "false") << std::endl;
第二种:带检查写法
if (doc.HasMember("param") && doc["param"].IsObject()) {const rapidjson::Value& param = doc["param"];if (param.HasMember("max_threshold") && param["max_threshold"].IsDouble()) {double max_threshold = param["max_threshold"].GetDouble();std::cout << "Max Threshold: " << max_threshold << std::endl;}if (param.HasMember("max_num") && param["max_num"].IsInt()) {int max_num = param["max_num"].GetInt();std::cout << "Max Num: " << max_num << std::endl;}if (param.HasMember("success") && param["success"].IsBool()) {bool success = param["success"].GetBool();std::cout << "Success: " << (success ? "true" : "false") << std::endl;}
}
(5)示例中的robot部分
{"robot": {"width": 1510,"length": 5180,"radius": 3420}
}
第一种:无检查写法
const rapidjson::Value& robot = doc["robot"];
int width = robot["width"].GetInt();
int length = robot["length"].GetInt();
int radius = robot["radius"].GetInt();std::cout << "Width: " << width << std::endl;
std::cout << "Length: " << length << std::endl;
std::cout << "Radius: " << radius << std::endl;
或
int width = doc["robot"]["width"].GetInt();
int length = doc["robot"]["length"].GetInt();
int radius = doc["robot"]["radius"].GetInt();std::cout << "Width: " << width << std::endl;
std::cout << "Length: " << length << std::endl;
std::cout << "Radius: " << radius << std::endl;
第二种:带检查写法
if (doc.HasMember("robot") && doc["robot"].IsObject()) {const rapidjson::Value& robot = doc["robot"];if (robot.HasMember("width") && robot["width"].IsInt()) {int width = robot["width"].GetInt();std::cout << "Width: " << width << std::endl;}if (robot.HasMember("length") && robot["length"].IsInt()) {int length = robot["length"].GetInt();std::cout << "Length: " << length << std::endl;}if (robot.HasMember("radius") && robot["radius"].IsInt()) {int radius = robot["radius"].GetInt();std::cout << "Radius: " << radius << std::endl;}
}
(6)示例中的other部分
{"other": []
}
第一种:仅检查数组是否为空
const rapidjson::Value& other = doc["other"];if (other.Empty()) {std::cout << "The 'other' array is empty." << std::endl;
} else {for (rapidjson::SizeType i = 0; i < other.Size(); ++i) {std::cout << "Element " << i << ": " << other[i].GetString() << std::endl;}
}
第二种:逐层检查写法
if (doc.HasMember("other") && doc["other"].IsArray()) {const rapidjson::Value& other = doc["other"];// 检查数组是否为空if (other.Empty()) {std::cout << "The 'other' array is empty." << std::endl;} else {// 遍历数组元素(如果有的话)for (rapidjson::SizeType i = 0; i < other.Size(); ++i) {std::cout << "Element " << i << ": " << other[i].GetString() << std::endl;}}
}
3、完整的程序示例 & 运行
(1)将以下内容存储为main.cpp
#include <iostream>
#include <fstream>
#include <string>
#include "rapidjson/document.h"
#include "rapidjson/istreamwrapper.h"/*** 使用rapidJSON解析JSON文件的函数* @param directory_path 文件所在的目录路径* @param file_name 文件名*/
void parseJSON(const std::string& directory_path, const std::string& file_name) {// 拼接完整的文件路径,判断 directory_path 是否为空,std::string full_file_path = directory_path.empty() ? file_name //若为空,说明要读取的json文件与当前可执行文件在同一目录下,则直接将file_name作为路径: (directory_path.back() == '/' // 判断 directory_path 的最后是否有 '/',若有则直接拼接 file_name,否则加上 '/'? directory_path + file_name : directory_path + "/" + file_name);// 打开JSON文件流std::ifstream ifs(full_file_path);if (!ifs.is_open()) {// 如果文件无法打开,输出错误信息并返回std::cerr << "无法打开文件: " << full_file_path << std::endl;return;}// 使用rapidJSON的IStreamWrapper包装文件流,方便解析rapidjson::IStreamWrapper isw(ifs);// 定义rapidJSON的Document对象,用于存储解析后的JSON数据rapidjson::Document document;document.ParseStream(isw);// 检查JSON文件解析是否成功if (document.HasParseError()) {// 如果解析失败,输出错误信息并返回std::cerr << "JSON解析错误!" << std::endl;return;}// 开始逐个解析JSON字段// 解析"Info"部分if (document.HasMember("Info")) { // 检查是否存在"Info"字段const rapidjson::Value& info = document["Info"];if (info.IsObject()) { // 确保"Info"是一个对象类型std::cout << "Info 部分解析结果:" << std::endl;// 读取作者信息if (info.HasMember("author") && info["author"].IsString()) {std::cout << "作者: " << info["author"].GetString() << std::endl; // 输出作者名称}// 读取版本号if (info.HasMember("version") && info["version"].IsString()) {std::cout << "版本: " << info["version"].GetString() << std::endl; // 输出版本号}// 读取编号if (info.HasMember("number") && info["number"].IsInt()) {std::cout << "编号: " << info["number"].GetInt() << std::endl; // 输出编号}// 读取位置数组if (info.HasMember("position") && info["position"].IsArray()) {std::cout << "位置: ";for (auto& pos : info["position"].GetArray()) {std::cout << pos.GetFloat() << " "; // 遍历并输出位置坐标}std::cout << std::endl;}// 读取速率if (info.HasMember("rate") && info["rate"].IsDouble()) {std::cout << "速率: " << info["rate"].GetDouble() << std::endl; // 输出速率}}}// 解析"scale"部分if (document.HasMember("scale") && document["scale"].IsInt()) {std::cout << "缩放比例: " << document["scale"].GetInt() << std::endl; // 输出缩放比例}// 解析"regions"部分if (document.HasMember("regions") && document["regions"].IsArray()) {std::cout << "区域解析:" << std::endl;const rapidjson::Value& regions = document["regions"];for (const auto& region : regions.GetArray()) { // 遍历区域数组// 输出区域索引if (region.HasMember("index") && region["index"].IsInt()) {std::cout << "区域索引: " << region["index"].GetInt() << std::endl;}// 输出区域名称if (region.HasMember("name") && region["name"].IsString()) {std::cout << "区域名称: " << region["name"].GetString() << std::endl;}// 输出区域点坐标if (region.HasMember("points") && region["points"].IsArray()) {std::cout << "区域点坐标:" << std::endl;for (const auto& point : region["points"].GetArray()) {if (point.HasMember("x") && point["x"].IsDouble() &&point.HasMember("y") && point["y"].IsDouble()) {std::cout << "x: " << point["x"].GetDouble() << ", y: " << point["y"].GetDouble() << std::endl;}}}}}// 解析"param"部分if (document.HasMember("param") && document["param"].IsObject()) {std::cout << "参数解析:" << std::endl;const rapidjson::Value& param = document["param"];// 输出最大阈值if (param.HasMember("max_threshold") && param["max_threshold"].IsDouble()) {std::cout << "最大阈值: " << param["max_threshold"].GetDouble() << std::endl;}// 输出最大数量if (param.HasMember("max_num") && param["max_num"].IsInt()) {std::cout << "最大数量: " << param["max_num"].GetInt() << std::endl;}// 输出成功状态if (param.HasMember("success") && param["success"].IsBool()) {std::cout << "是否成功: " << (param["success"].GetBool() ? "是" : "否") << std::endl;}}// 解析"robot"部分if (document.HasMember("robot") && document["robot"].IsObject()) {std::cout << "机器人参数:" << std::endl;const rapidjson::Value& robot = document["robot"];// 输出机器人宽度if (robot.HasMember("width") && robot["width"].IsInt()) {std::cout << "宽度: " << robot["width"].GetInt() << std::endl;}// 输出机器人长度if (robot.HasMember("length") && robot["length"].IsInt()) {std::cout << "长度: " << robot["length"].GetInt() << std::endl;}// 输出机器人半径if (robot.HasMember("radius") && robot["radius"].IsInt()) {std::cout << "半径: " << robot["radius"].GetInt() << std::endl;}}// 解析"other"部分if (document.HasMember("other") && document["other"].IsArray()) {std::cout << "其他信息: " << (document["other"].Empty() ? "空" : "存在内容") << std::endl;}// 关闭文件流ifs.close();
}int main() {// 调用解析函数,传入JSON文件所在目录路径和文件名parseJSON("", "test.json");return 0;
}
(2)在与main.cpp的同一目录下,将以下内容存储为test.json
{"Info": {"author": "JZX_MY","version": "v1.0.96","number": 66,"position": [-9, 60.0, 10.0],"rate": 0.99},"scale": 77,"regions": [{"index": 0,"name": "free_regions","points": [{"x": -2.03,"y": 2.25},{"x": 1.39,"y": 5.82},{"x": 7.47,"y": 2.35},{"x": 5.50,"y": -1.36}]},{"index": 1,"name": "occupy_regions","points": [{"x": -2.03,"y": 27.25},{"x": 10.39,"y": 5.82},{"x": 78.47,"y": 2.35}]}],"param": {"max_threshold": 0.05,"max_num" : 10240,"success" : true},"robot": {"width": 1510,"length": 5180,"radius": 3420},"other": []
}
(3)在存储以上两个文件的目录下的终端运行以下指令进行编译
g++ main.cpp -o main
(4)继续在该终端下,运行以下指令,运行程序
./main
(5)可以看到如下所示的运行结果
Info 部分解析结果:
作者: JZX_MY
版本: v1.0.96
编号: 66
位置: -9 60 10
速率: 0.99
缩放比例: 77
区域解析:
区域索引: 0
区域名称: free_regions
区域点坐标:
x: -2.03, y: 2.25
x: 1.39, y: 5.82
x: 7.47, y: 2.35
x: 5.5, y: -1.36
区域索引: 1
区域名称: occupy_regions
区域点坐标:
x: -2.03, y: 27.25
x: 10.39, y: 5.82
x: 78.47, y: 2.35
参数解析:
最大阈值: 0.05
最大数量: 10240
是否成功: 是
机器人参数:
宽度: 1510
长度: 5180
半径: 3420
其他信息: 空
以上综合示例的相关文件,我已经放在了本文的绑定附件中,有需要可以自行获取。
相关文章:
详细介绍如何使用rapidjson读取json文件
本文主要详细介绍如何使用rapidjson库来实现.json文件的读取,分为相关基础介绍、结合简单示例进行基础介绍、结合复杂示例进行详细的函数实现介绍等三部分。 一、相关基础 1、Json文件中的{} 和 [] 在 JSON 文件中,{} 和 [] 分别表示不同的数据结构&…...
Mybatis 如何复用 SQL
比如你的Mapper是这样写的: 但这个接口是没有分页的,你还想再写一个有分页的查询接口,两个接口SQL一模一样,只是多了分页特性。你可以直接重载一个方法,增加分页参数,即可复用该SQL。如下:...
使用 Python 操作 MySQL 数据库的实用工具类:MySQLHandler
操作数据库是非常常见的需求,使用 Python 和 pymysql 库封装一个通用的 MySQL 数据库操作工具类,并通过示例演示如何使用这个工具类高效地管理数据库。 工具类的核心代码解析 MySQLHandler 类简介 MySQLHandler 是一个 Python 类,用于简化…...
C++ 内存管理:原理、技巧与实战
目录 第一章:C++ 内存管理基础 1.1 C++ 内存布局剖析 1.2 内存分配与释放:核心机制详解 1.2.1 new/delete 操作符 1.2.2 malloc/free 函数 第二章:智能指针 —— 内存管理利器 2.1 智能指针概览 2.2 常用智能指针类型 2.2.1 unique_ptr 2.2.2 shared_ptr 2.2.3 we…...
算法学习(17)—— FloodFill算法
目录 关于FloodFill算法 部分OJ题详解 733. 图像渲染 200. 岛屿数量 695. 岛屿的最大面积 130. 被围绕的区域 417. 太平洋大西洋水流问题 529. 扫雷问题 LCR130. 衣橱整理 关于FloodFill算法 爆搜,深搜,回溯的算法原理并不难,这类题…...
Kubernetes ConfigMap的创建与使用
前提条件 拥有Kubernetes集群环境,可参考:Kubernetes集群搭建理解Kubernetes部署知识,可参考:使用Kubernetes部署第一个应用 、Deloyment控制器 ConfigMap简介 ConfigMap 是 Kubernetes(通常简称为 K8s)中…...
灵当CRM uploadfile.php 文件上传致RCE漏洞复现
0x01 产品简介 灵当CRM是一款专为中小企业打造的智能客户关系管理工具,由上海灵当信息科技有限公司开发并运营。广泛应用于金融、教育、医疗、IT服务、房地产等多个行业领域,帮助企业实现客户个性化管理需求,提升企业竞争力。无论是新客户开拓、老客户维护,还是销售过程管…...
老旧小区用电安全保护装置#限流式防火保护器参数介绍#
摘要 随着居民住宅区用电负荷的增加,用电安全问题日益突出,火灾隐患频繁发生。防火限流式保护器作为一种新型电气安全设备,能够有效预防因电气故障引发的火灾事故。本文介绍了防火限流式保护器的工作原理、技术特点及其在居民住宅区用电系统…...
在git commit之前让其自动执行一次git pull命令
文章目录 背景原因编写脚本测试效果 背景原因 有时候可以看到项目的git 提交日志里好多 Merge branch ‘master’ of …记录。这些记录是怎么产生的呢? 是因为在本地操作 git add . 、 git commit -m "xxxxx"时,没有提前进行git pull操作&…...
【实现100个unity特效之4】Unity ShaderGraph使用教程与各种特效案例(2023/12/1更新)
文章目录 一、前言二、ShaderGraph1.什么是ShaderGraph2.在使用ShaderGraph时需要注意以下几点:3.优势4.项目 三、实例效果边缘发光进阶:带方向的菲涅尔边缘光效果裁剪进阶 带边缘色的裁剪溶解进阶 带边缘色溶解卡通阴影水波纹积雪效果不锈钢效果、冰晶效…...
单机和微服务的区别,微服务有什么问题?数据一致性问题怎么解决?幂等问题怎么解决?
单机和微服务的区别,微服务有什么问题?数据一致性问题怎么解决?幂等问题怎么解决? 单机架构和微服务架构在设计理念、部署和扩展性上有显著区别。 单机架构 vs 微服务架构 单机架构 定义:所有组件(前端…...
McDonald‘s Event-Driven Architecture 麦当劳事件驱动架构
原文链接 1 mcdonalds-technical-blog/ 原文链接 2 mcdonalds-technical-blog/ 麦当劳在异步、事务性和分析性处理用例中使用跨技术栈的事件,包括移动订单进度跟踪和向客户发送营销通信(交易和促销)。 统一事件平台(unified eve…...
Clickhouse(Centos)
地址信息 官网地址:Fast Open-Source OLAP DBMS - ClickHouse 下载地址:packages.clickhouse.com/rpm/stable/ 1.clickhouse-client-23.1.3.5.x86_64.rpm 2.clickhouse-common-static-23.1.3.5.x86_64.rpm 3.clickhouse-common-static-dbg-23.1.3.5.x86_…...
赛博错题本
机构抽象老师非得让我们整一个错题本,我寻思都学计算机了,还在整高中做题呢一套是什么意思呢,更何况考试也就一周一次,你整个本完完全全没有必要,整个赛博错题本得了。以后错题都会存在这里,基本上一周一更…...
【MySQL初阶】Ubuntu 环境安装 MySQL
🎉博主首页: 有趣的中国人 🎉专栏首页: 数据库初阶 🎉其它专栏: C初阶 | C进阶 | 初阶数据结构 小伙伴们大家好,本片文章将会讲解 Ubuntu 系统安装 MySQL 的相关内容。 如果看到最后您觉得这篇…...
【Kubernetes 指南】基础入门——Kubernetes 基本概念(二)
目录 二、Pod 1、Pod 简介 2、Pod 图示 3、nginx 容器 二、Pod 1、Pod 简介 - Kubernetes 使用 Pod 来管理容器,每个 Pod 可以包含一个或多个紧密关联的容器。 - Pod 是一组紧密关联的容器集合,它们共享 PID、IPC、Network 和 UTS namespace&#…...
Ubuntu系统下 npm install -g tauri 报错问题处理
处理在安装 Tauri 时遇到的问题,可以按照以下步骤进行操作 npm install -g taurinpm warn deprecated inflight1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async …...
数字逻辑(六)——下载Digital软件
Digital是一种用于设计和仿真数字逻辑电路的教育工具,它是免费、开源和跨平台的。这款软件十分适合新人,可以使用画简单的电路。 1 下载Digital软件 首先Digital的下载地址是: https://github.com/hneemann/Digital 下载完成之后&…...
Ruby Raider使用教程
Ruby Raider是什么? Ruby Raider 是一款生成器和脚手架 gem,可让 UI 测试自动化更容易 Github链接:https://github.com/RaiderHQ/ruby_raider 目前支持的框架 Web自动化测试 Cucumber and Selenium Rspec and Selenium Cucumber and Wa…...
音视频入门基础:AAC专题(13)——FFmpeg源码中,获取ADTS格式的AAC裸流音频信息的实现
音视频入门基础:AAC专题系列文章: 音视频入门基础:AAC专题(1)——AAC官方文档下载 音视频入门基础:AAC专题(2)——使用FFmpeg命令生成AAC裸流文件 音视频入门基础:AAC…...
Spring Boot 中的 @Scheduled 定时任务以及开关控制
Scheduled注解是Spring框架(包括Spring Boot)中用于实现定时任务的一种方式。以下是对Scheduled注解的详细解析: 一、基本概念 Scheduled注解允许开发者在Spring容器中定义定时任务。通过简单地在一个方法上添加Scheduled注解,S…...
基于PXE与NFS共享的Ubuntu安装配置过程
假设存在服务器A、B、C 其中A为待装系统的服务器,DHCP(IP池:192.168.0.150~192.168.0.160),假设需要安装的系统为Ubuntu 22.04 Desktop 其中B为PXE服务端服务器,IP: 192.168.0.100,这里将以Cent…...
Dots 常用操作
游戏中有多个蚂蚁群落,每个蚂蚁属于一个群落,如何设计数据结构? 方法1:为蚂蚁组件添加一个属性 ID,会造成逻辑中大量分支语句,如果分支语句逻辑不平衡可能带来 Job 调度问题,每个蚂蚁会有一份蚂…...
力扣-图论-20【算法学习day.70】
前言 ###我做这类文章一个重要的目的还是给正在学习的大家提供方向和记录学习过程(例如想要掌握基础用法,该刷哪些题?)我的解析也不会做的非常详细,只会提供思路和一些关键点,力扣上的大佬们的题解质量是非…...
ModbusTCP从站转Profinet主站案例
一. 案例背景 在复杂的工业自动化场景中,企业常常会采用不同品牌的设备来构建生产系统。西门子SINAMICS G120变频器以其高性能、高精度的速度和转矩控制功能,在电机驱动领域应用广泛。施耐德M580可编程逻辑控制器则以强大的逻辑控制和数据处理能力著称&…...
Linux 线程池
1.概念介绍 线程池是一种多线程处理形式,它维护着多个线程,这些线程处于等待状态,随时准备接受任务并执行。线程池的主要目的是为了提高系统的性能和资源利用率,避免在处理短时间任务时频繁创建和销毁线程所带来的开销。 线程池…...
计算机视觉目标检测-1
文章目录 摘要Abstract1.目标检测任务描述1.1 目标检测分类算法1.2 目标定位的简单实现思路1.2.1 回归位置 2.R-CNN2.1 目标检测-Overfeat模型2.1.1 滑动窗口 2.2 目标检测-RCNN模型2.2.1 非极大抑制(NMS) 2.3 目标检测评价指标 3.SPPNet3.1 spatial pyr…...
2024最新鸿蒙开发面试题合集(一)-HarmonyOS NEXT Release(API 12 Release)
1. HarmonyOS应用打包后的文件扩展名是? 打包后的文件扩展名为.hap(HarmonyOS Ability Package),这是HarmonyOS应用的标准包格式 2. 页面和自定义组件生命周期有哪些? 页面和自定义组件生命周期说明 有Entry装饰器的component组件的生命…...
HarmonyOS NEXT 实战之元服务:静态案例效果--航空出行
背景: 前几篇学习了元服务,后面几期就让我们开发简单的元服务吧,里面丰富的内容大家自己加,本期案例 仅供参考 先上本期效果图 ,里面图片自行替换 效果图1完整代码案例如下: import { authentication } …...
详解 Python 中的json.loads和json.dumps方法:中英双语
中文版 详解 Python 中的 json.loads 和 json.dumps 方法 在 Python 的标准库中,json 模块用于处理 JSON 数据格式。JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,广泛用于前后端交互以及数据存储。json.loads …...
成方金融科技后端部分笔试题 - 解析
单选题 1.以下关于JAVA自动类型转换,描述错误的是哪一项?(B) A.byte->short B.char->short C.char->int D.float->double 2.请选择运行以下代码后,系统显示的内容什么?(B) public class Test {static {int x1;}static int x,y;publ…...
互联网视频云平台EasyDSS无人机推流直播技术如何助力野生动植物保护工作?
在当今社会,随着科技的飞速发展,无人机技术已经广泛应用于各个领域,为我们的生活带来了诸多便利。而在动植物保护工作中,无人机的应用更是为这一领域注入了新的活力。EasyDSS,作为一款集视频处理、分发、存储于一体的综…...
Vue3 中使用axios
1.安装axios、js-cookie、pinia axios命令行: npm install axios js-cookie命令行: npm install js-cookie store命令行: npm install pinia 2.配置文件 (1)缓存文件配置 src/plugins/auth.js const sessionCache {set (key, valu…...
【JAVA高级篇教学】第五篇:OpenFeign 微服务调用注意事项
在微服务架构中,OpenFeign 是一种常用的 HTTP 客户端工具,用于实现服务之间的调用。它提供了声明式的接口调用方式,大幅简化了开发工作。然而,在实际使用中,需要注意一些细节,尤其是在处理 GET、POST 请求和…...
Llama 3 简介(一)
目录 1. 引言 1.1 Llama 3 的简介 1.2 性能评估 1.3 开源计划 1.4 多模态扩展 ps 1. 缩放法则 2. 超额训练(Over-training) 3. 计算训练预算 4. 如何逐步估算和确定最优模型? 2. 概述 2.1 Llama 3 语言模型开发两个主要阶段 2.2…...
路由器做WPAD、VPN、透明代理中之间一个
本文章将采用家中TP-Link路由器 路由器进行配置DNS DNS理解知识本文DNS描述参考:网络安全基础知识&中间件简单介绍_计算机网络中间件-CSDN博客 TP LINK未知的错误,错误编号:-22025 TP-LINK 认证界面地址:https://realnam…...
Xcode 16 编译弹窗问题、编译通过无法,编译通过打包等问题汇总
问题1:打包的过程中不断提示 :codesign 想要访问你的钥匙串中的密钥“develop 或者distribution 证书” 解决:打开钥匙串,点击证书---显示简介---信任----改为始终信任 (记住 :不能只修改钥匙的显示简介的…...
【编辑器扩展】打开持久化路径/缓存路径/DataPath/StreamingAssetsPath文件夹
代码 [MenuItem("Assets/Open Explorer/PersistentDataPath")]public static void OpenPersistentDataPath(){Application.OpenURL(Application.persistentDataPath);}[MenuItem("Assets/Open Explorer/DataPath")]public static void OpenDataPath(){Appl…...
shardingsphere分库分表项目实践1-让shardingsphere运行起来
学习新技术最快的方式就是: 1. 先找一个比较完善的demo跑起来 2. 弄清楚用法:配置、原理、使用场景 3. 移植到自己项目上,按照自己需求进行修改优化。 找demo项目的方法:优先去官方git库找,如果没有或者过于简单那么…...
Java预加载
预加载(Preload)是一种在程序运行之前预先加载所需资源或对象的优化技术,旨在提高程序的性能和响应速度。以下是对预加载的详细解释: 一、预加载的定义 预加载是指在程序实际运行之前,将预计会频繁使用的资源&#x…...
Vue3之状态管理Vuex
Vuex作为Vue.js的官方状态管理库,在大型或复杂的前端项目中扮演着至关重要的角色。本文将从Vuex的原理、特点、应用场景等多个方面进行深入解析,并通过代码示例展示如何在Vuex中实现特定功能。 一、Vuex原理 Vuex是一个专为Vue.js应用程序开发的状态管…...
优化 invite_codes 表的 SQL 创建语句
-- auto-generated definition create table invite_codes (id int auto_incrementprimary key,invite_code varchar(6) not null comment 邀请码,6位整数,确保在有效期内…...
ctfhub disable_functions关卡
1.CTFHub Bypass disable_function —— LD_PRELOAD 2.CTFHub Bypass disable_function —— ShellShock 3.CTFHub Bypass disable_function —— Apache Mod CGI 4.CTFHub Bypass disable_function —— 攻击PHP-FPM 5.CTFHub Bypass disable_function —— GC UAF 6.CTFHub B…...
Pikachu 漏洞练习平台 XXE漏洞学习记录
懒得自己搭建的可以直接FOFA找别人的靶场玩 FOFA "Pikachu 漏洞练习平台" 开始 随便输入个包含命名实体(内部实体)的xml数据(以下代码中xxe是命名实体的实体名称): <?xml version"1.0"?>…...
机器学习基础 衡量模型性能指标
目录 1 前言 编辑1.1 错误率(Error rate)&精度(Accuracy)&误差(Error): 1.2 过拟合(overfitting): 训练误差小,测试误差大 1.3 欠拟合(underfitting):训练误差大,测试误差大 1.4 MSE: 1.5 RMSE: 1.6 MAE: 1.7 R-S…...
C#—内建接口: IEnumerable与IEnumerator接口详解
IEnumerable接口 在C#中,IEnumerable 是一个泛型接口,它表示一个可以通过 IEnumerator 迭代器进行迭代枚举的集合。这个接口是非常基础且重要的,因为它允许开发者以一致的方式遍历任何实现了该接口的集合,无论是数组、列表、自定…...
java日志框架:slf4j、jul(java.util.logging)、 log4j、 logback
SLF4J--抽象接口 SLF4J (Simple Logging Facade for Java) 是一个为各种 Java 日志框架提供简单统一接口的库。它的主要目的是将应用程序代码与具体的日志实现解耦,使得在不修改应用程序代码的情况下,可以轻松地切换不同的日志框架。 jul-to-slft4j.ja…...
SpringBoot 事务
事务是一组操作的集合, 是一个不可分割的操作.会把所有的操作作为一个整体, 一起向数据库提交或者是撤销操作请求. 所以这组操作要么同时成功, 要么同时失败. 为什么需要事务? 我们在进行程序开发时, 也会有事务的需求. 比如转账操作: 第一步:A 账户 -100 元. …...
airflow docker 安装
mkdir -p /root/airflow cd /root/airflow && mkdir -p ./dags ./logs ./plugins ./configcd /root/airflow/ wget https://airflow.apache.org/docs/apache-airflow/2.10.4/docker-compose.yaml nano docker-compose.yamlAIRFLOW__CORE__LOAD_EXAMPLES: false #初始化…...
如何用gpt来分析链接里面的内容(比如分析论文链接)和分析包含多个文件中的一块代码
如何用gpt来分析链接里面的内容,方法如下 这里使用gpt4里面有一个网路的功能 点击搜索框下面这个地球的形状即可启动搜索网页模式 然后即可提出问题在搜索框里:发现正确识别和分析了链接里面的内容 链接如下:https://arxiv.org/pdf/2009.1…...