当前位置: 首页 > news >正文

手机网站 win8风格中信建设有限责任公司客户

手机网站 win8风格,中信建设有限责任公司客户,网站免费推广,WordPress1001无标题本文主要详细介绍如何使用rapidjson库来实现.json文件的读取#xff0c;分为相关基础介绍、结合简单示例进行基础介绍、结合复杂示例进行详细的函数实现介绍等三部分。 一、相关基础 1、Json文件中的{} 和 [] 在 JSON 文件中#xff0c;{} 和 [] 分别表示不同的数据结构分为相关基础介绍、结合简单示例进行基础介绍、结合复杂示例进行详细的函数实现介绍等三部分。 一、相关基础 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。 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_castfloat(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_castfloat(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 fstreamint 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 和字段类型检查确保数据完整性。字段提取通过 GetType() 函数提取具体数据。 这种方法适用于处理结构明确的 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 main4继续在该终端下运行以下指令运行程序 ./main5可以看到如下所示的运行结果 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 其他信息: 空 以上综合示例的相关文件我已经放在了本文的绑定附件中有需要可以自行获取。
http://www.sczhlp.com/news/215885/

相关文章:

  • 网站建设有哪些渠道开网店要建网站平台吗
  • 怎么样备份网站数据库装修公司排行榜
  • cc域名做网站好吗东莞常平碧桂园铂悦府
  • 东莞网站建设设计做服务器的网站都有哪些
  • uploads-lab通关攻略
  • 中国企业DevOps工具链选型指南:政务、出海与跨国协作的实战解析
  • 初始化vue3项目和打包vue3项目
  • Continuation Passing Style 连续传递样式
  • 浙江宝业建设集团网站汕头响应式网站
  • 天津网站营销网站悬浮窗口
  • 家具东莞网站建设0769知道创宇 wordpress
  • 直播网站怎么建设自助建站的一般流程
  • 建设银行网站怎么交学费网站建设预算表样本
  • 石家庄seo网站排名广州冼村属于哪个区
  • 加油站项目建设背景装修公司网站怎么做的
  • s网站建设汕头建设吧百度贴吧
  • 卖保温杯去什么网站做推广长沙房地产价格
  • 黑客入侵别人网站做seo在家做农业关注什么网站
  • 网站怎么改域名广西建设厅官网证件查询
  • 微网站开发技术华宁网站建设
  • 十大高端网站定制设计抖音电商
  • 衡阳市住房和城乡建设局官方网站芗城网站建设
  • 如何做微信下单小程序深圳seo网站推广公司
  • 科技广告公司网站建设如何找人做网站
  • 学做网站论坛做网站阜新
  • 完整的网站开发自适应网站一般做多大尺寸
  • 松江品划做企业网站无锡网页建站公司
  • 城乡住房和城乡建设厅网站wordpress漫画站主题
  • 网站建设最基础是什么做网站v1认证需要付费吗
  • 做响应式网站浙江省互联网建设网站