diff --git a/Inc/Json_Utilities.hpp b/Inc/Json_Utilities.hpp index 955ac4a..b6a4b6a 100644 --- a/Inc/Json_Utilities.hpp +++ b/Inc/Json_Utilities.hpp @@ -21,6 +21,23 @@ class Json_Value; // Json 值(可以是数组、对象、字符串、浮点 */ std::string JsonFile_FormatCheck(const char *path_to_file); +/** + * @brief 解析Json文件 + * @param path_to_file 文件路径串 + * @param pJson_Value Value 指针 + * @return std::string 错误值 + */ +std::string JsonFile_Parse(const char *path_to_file, Json_Value *pJson_Value); + +/** + * @brief Json对象保存 + * @param path_to_file 文件路径串 + * @param value Json Value + * @param enable_pretty_print 启用美观打印 + * @return std::string 错误值 + */ +std::string Json_Export(const char *path_to_file, Json_Value value, bool enable_pretty_print = true); + // Json 数组 class Json_Arry { @@ -29,6 +46,9 @@ private: std::vector private_element_list; public: + // 只读引用 + const std::vector &element_list = this->private_element_list; + // 默认构造 Json_Arry() = default; // 列表构造 @@ -38,12 +58,12 @@ public: // 深拷贝 Json_Arry &operator=(const Json_Arry &another); // 获取元素大小 - size_t size(void); + size_t size(void) const; // 数组索引重载 - Json_Value operator[](size_t index); + Json_Value operator[](size_t index) const; // 是否为空 - bool isNull(void); + bool isNull(void) const; }; // Json 值定义 @@ -92,15 +112,15 @@ public: ~Json_Value(); // 获取值 - std::string asString(void); - Json_Arry asArry(void); - Json_Object asObject(void); - int64_t asInteger(void); - double asFloat(void); - bool asBoolean(void); + std::string asString(void) const; + Json_Arry asArry(void) const; + Json_Object asObject(void) const; + int64_t asInteger(void) const; + double asFloat(void) const; + bool asBoolean(void) const; // 是否为空 - bool isNull(void); + bool isNull(void) const; }; // Json 键值对定义 @@ -126,7 +146,7 @@ public: Json_Pair &operator=(const Json_Pair &another); // 空判定 - bool isNull(); + bool isNull() const; }; // Json 对象 @@ -137,6 +157,9 @@ private: std::vector private_element_list; public: + // 只读引用 + std::vector const &element_list = this->private_element_list; + // 默认构造 Json_Object() = default; // 列表构造 @@ -147,15 +170,15 @@ public: Json_Object &operator=(const Json_Object &another); // 获取元素大小 - size_t size(void); + size_t size(void) const; // 数组索引重载 - Json_Pair operator[](size_t index); + Json_Pair operator[](size_t index) const; // 由Key 查找值 - Json_Value get(std::string key); + Json_Value get(std::string key) const; // 是否为空 - bool isNull(void); + bool isNull(void) const; }; #endif \ No newline at end of file diff --git a/Src/Json_Utilities.cpp b/Src/Json_Utilities.cpp index 78d62ac..508e581 100644 --- a/Src/Json_Utilities.cpp +++ b/Src/Json_Utilities.cpp @@ -4,6 +4,7 @@ extern "C" { #include "stdio.h" #include "stdlib.h" +#include "string.h" } #include "functional" @@ -211,14 +212,13 @@ std::string JsonFile_FormatCheck(const char *path_to_file) column_count++; switch (ch_get) { - case EOF: - return std::string(path_to_file) + ':' + std::to_string(rol_count) + ':' + std::to_string(column_count) + ": Unexpected EOF."; case '\r': case ',': case '}': case ']': column_count--; fseek(pFile, -1, SEEK_CUR); + case EOF: case ' ': case '\n': segment_finish = true; @@ -385,7 +385,8 @@ std::string JsonFile_FormatCheck(const char *path_to_file) err_str = std::string(path_to_file) + ':' + std::to_string(rol_count) + ':' + std::to_string(column_count) + ": Unexpected EOF."; break; default: - err_str = std::string(path_to_file) + ':' + std::to_string(rol_count) + ':' + std::to_string(column_count) + ": Syntax error. Must begin with '{' or '['."; + fseek(pFile, -1, SEEK_CUR); + err_str = Check_Value(); } // 关闭文件 @@ -393,6 +394,417 @@ std::string JsonFile_FormatCheck(const char *path_to_file) return err_str; } +/** + * @brief 解析Json文件 + * @param path_to_file 文件路径串 + * @param pJson_Value Value 指针 + * @return std::string 错误值 + */ +std::string JsonFile_Parse(const char *path_to_file, Json_Value *pJson_Value) +{ + // 存在格式错误时返回NULL值,通过格式检查时信任后续的输入 + std::string err_str = JsonFile_FormatCheck(path_to_file); + if (!err_str.empty()) + return err_str; + + // 尝试打开文件 + FILE *pFile = fopen(path_to_file, "rb"); + if (pFile == nullptr) + return "file \"" + std::string(path_to_file) + "\" open failed."; + + // 跳过空白部分 return -> skip count + auto Lambda_skip_blank = [&](void) -> size_t + { + size_t read_count = 0; + while (true) + { + switch (fgetc(pFile)) + { + case EOF: + return read_count; + case ' ': + read_count++; + break; + case '\r': + if (fgetc(pFile) == '\n') + { + read_count += 2; + } + else + { + fseek(pFile, -2, SEEK_CUR); + return read_count; + } + break; + case '\n': + read_count++; + break; + default: + fseek(pFile, -1, SEEK_CUR); + return read_count; + } + } + }; + + // 函数封装 + std::function Parse_Object; + std::function Parse_Value; + std::function Parse_Arry; + std::function Parse_Pair; + + // 函数定义 + Parse_Object = [&](void) -> Json_Object + { + Json_Object temp_obj; + Lambda_skip_blank(); + + // 拿掉第一个 '{' + char ch_get = fgetc(pFile); + + while (true) + { + Lambda_skip_blank(); + ch_get = fgetc(pFile); + + switch (ch_get) + { + case '}': + return temp_obj; + case '\"': + fseek(pFile, -1, SEEK_CUR); + { + std::vector pair_list = temp_obj.element_list; + pair_list.push_back(Parse_Pair()); + temp_obj = Json_Object(pair_list); + } + break; + default: + break; + } + } + }; + + Parse_Value = [&](void) -> Json_Value + { + Lambda_skip_blank(); + + bool is_string = false; + char ch_get = fgetc(pFile); + + // 判定第一个字符 + switch (ch_get) + { + case '\"': + is_string = true; + break; + case '{': + fseek(pFile, -1, SEEK_CUR); + return Parse_Object(); + case '[': + fseek(pFile, -1, SEEK_CUR); + return Parse_Arry(); + default: + break; + } + + // 判定为字符串 + if (is_string) + { + std::string value_str; + while (true) + { + ch_get = fgetc(pFile); + + switch (ch_get) + { + case '\"': + return value_str; + case '\\': // 转义符 + ch_get = fgetc(pFile); + value_str.push_back('\\'); + value_str.push_back(ch_get); + break; + default: + value_str.push_back(ch_get); + continue; + } + } + } + else + fseek(pFile, -1, SEEK_CUR); + + // 识别非字符串类型Json值 + std::string segment_read; + while (true) + { + bool segment_finish = false; + + ch_get = fgetc(pFile); + switch (ch_get) + { + case '\r': + case ',': + case '}': + case ']': + fseek(pFile, -1, SEEK_CUR); + case EOF: + case ' ': + case '\n': + segment_finish = true; + break; + default: + segment_read += ch_get; + } + + if (segment_finish) + break; + } + + // 逻辑值识别 + if (segment_read == "true") + return true; + if (segment_read == "false") + return false; + if (segment_read == "null") + return Json_Value(); + + // 数值识别 + if (strstr(segment_read.c_str(), "e") || strstr(segment_read.c_str(), ".")) + return strtod(segment_read.c_str(), nullptr); + else + return strtoll(segment_read.c_str(), nullptr, 0); + }; + + Parse_Arry = [&](void) -> Json_Arry + { + Lambda_skip_blank(); + + // 拿掉第一个 '[' + char ch_get = fgetc(pFile); + + std::vector value_list; + while (true) + { + Lambda_skip_blank(); + ch_get = fgetc(pFile); + + switch (ch_get) + { + case ']': + return value_list; + case ',': + break; + default: + fseek(pFile, -1, SEEK_CUR); + value_list.push_back(Parse_Value()); + } + } + }; + + Parse_Pair = [&](void) -> Json_Pair + { + std::string key_str; + Lambda_skip_blank(); + + // 拿掉第一个 '\"' + char ch_get = fgetc(pFile); + + // 遍历下一个引号 + bool key_end = false; + while (true) + { + ch_get = fgetc(pFile); + + switch (ch_get) + { + case '\"': + key_end = true; + break; + default: + key_str.push_back(ch_get); + break; + } + + if (key_end) + break; + } + + // 拿掉键值对标记 + Lambda_skip_blank(); + ch_get = fgetc(pFile); + + // 返回键值对 + return Json_Pair(key_str, Parse_Value()); + }; + + // 跳过空白检查第一个字符 + Lambda_skip_blank(); + switch (fgetc(pFile)) + { + case '[': + fseek(pFile, -1, SEEK_CUR); + *pJson_Value = Parse_Arry(); + break; + case '{': + fseek(pFile, -1, SEEK_CUR); + *pJson_Value = Parse_Object(); + break; + default: + fseek(pFile, -1, SEEK_CUR); + *pJson_Value = Parse_Value(); + break; + } + + fclose(pFile); + return std::string(); +} + +/** + * @brief Json对象保存 + * @param path_to_file 文件路径串 + * @param value Json Value + * @param enable_pretty_print 启用美观打印 + * @return std::string 错误值 + */ +std::string Json_Export(const char *path_to_file, Json_Value value, bool enable_pretty_print) +{ + // 打开文件 + FILE *pFile = fopen(path_to_file, "wb"); + if (pFile == nullptr) + { + fclose(pFile); + return "file \"" + std::string(path_to_file) + "\" open failed."; + } + // 函数封装 + std::function Export_Object; + std::function Export_Value; + std::function Export_Arry; + std::function Export_Pair; + + // 函数定义 + Export_Object = [&](const Json_Object &obj, size_t depth, bool first_line_indent) + { + // 首行缩进 + if (enable_pretty_print && first_line_indent) + for (size_t count = 0; count < depth; count++) + fprintf(pFile, " "); + + // 对象起始 + fprintf(pFile, "{"); + if (enable_pretty_print && (!obj.isNull())) + fprintf(pFile, "\r\n"); + + // 输出键值对 + for (auto pair : obj.element_list) + { + Export_Pair(pair, depth + 1); + fprintf(pFile, enable_pretty_print ? ",\r\n" : ","); + } + if (!obj.isNull()) + { + fseek(pFile, enable_pretty_print ? -3 : -1, SEEK_CUR); + if (enable_pretty_print) + fprintf(pFile, "\r\n"); + } + + // 尾部缩进 + if (enable_pretty_print && (!obj.isNull())) + for (size_t count = 0; count < depth; count++) + fprintf(pFile, " "); + + // 对象结束 + fprintf(pFile, "}"); + }; + + Export_Value = [&](const Json_Value &value, size_t depth, bool indent) + { + if (enable_pretty_print && indent) + for (size_t count = 0; count < depth; count++) + fprintf(pFile, " "); + switch (value.type) + { + case Json_Value::TYPE_NULL: // 空值 + fprintf(pFile, "null"); + break; + case Json_Value::TYPE_STR: // 字符串 + fprintf(pFile, "\"%s\"", value.asString().c_str()); + break; + case Json_Value::TYPE_ARRY: // 数组 + Export_Arry(value.asArry(), depth, false); + break; + case Json_Value::TYPE_OBJ: // 对象 + Export_Object(value.asObject(), depth, false); + break; + case Json_Value::TYPE_NUM_INTEGER: // 整数常数 + fprintf(pFile, "%lld", value.asInteger()); + break; + case Json_Value::TYPE_NUM_FLOAT: // 浮点常数 + fprintf(pFile, "%e", value.asFloat()); + break; + case Json_Value::TYPE_BOOLEAN: // 布尔逻辑值 + if (value.asBoolean() == true) + fprintf(pFile, "true"); + else + fprintf(pFile, "false"); + } + }; + + Export_Pair = [&](const Json_Pair &pair, size_t depth) + { + if (enable_pretty_print) + for (size_t count = 0; count < depth; count++) + fprintf(pFile, " "); + + fprintf(pFile, "\"%s\":", pair.key.c_str()); + if (enable_pretty_print) + fprintf(pFile, " "); + Export_Value(pair.value, depth, false); + }; + + Export_Arry = [&](const Json_Arry &arry, size_t depth, bool first_line_indent) + { + // 首行缩进 + if (enable_pretty_print && first_line_indent) + for (size_t count = 0; count < depth; count++) + fprintf(pFile, " "); + + // 数组起始 + fprintf(pFile, "["); + if (enable_pretty_print && (!arry.isNull())) + fprintf(pFile, "\r\n"); + + // 输出数组数值 + for (auto value : arry.element_list) + { + Export_Value(value, depth + 1, true); + fprintf(pFile, enable_pretty_print ? ",\r\n" : ","); + } + if (!arry.isNull()) + { + fseek(pFile, enable_pretty_print ? -3 : -1, SEEK_CUR); + if (enable_pretty_print) + fprintf(pFile, "\r\n"); + } + // 尾部缩进 + if (enable_pretty_print && (!value.isNull())) + for (size_t count = 0; count < depth; count++) + fprintf(pFile, " "); + + // 对象结束 + fprintf(pFile, "]"); + }; + + if (value.type == Json_Value::TYPE_OBJ) + Export_Object(value.asObject(), 0, false); + else if (value.type == Json_Value::TYPE_ARRY) + Export_Arry(value.asArry(), 0, false); + else + Export_Value(value, 0, false); + + fclose(pFile); + return std::string(); +} + // std::string 构造 Json_Value::Json_Value(std::string str) : private_type(TYPE_STR), p_mem(malloc(sizeof(str))) { @@ -469,17 +881,26 @@ Json_Value &Json_Value::operator=(const Json_Value &another) case TYPE_STR: this->p_mem = malloc(sizeof(std::string)); if (this->p_mem != nullptr) - new (this->p_mem) std::string(*((std::string *)another.p_mem)); + { + new (this->p_mem) std::string(); + *((std::string *)this->p_mem) = *((std::string *)another.p_mem); + } break; case TYPE_ARRY: this->p_mem = malloc(sizeof(Json_Arry)); if (this->p_mem != nullptr) - new (this->p_mem) Json_Arry(*((Json_Arry *)another.p_mem)); + { + new (this->p_mem) Json_Arry(); + *((Json_Arry *)this->p_mem) = *((Json_Arry *)another.p_mem); + } break; case TYPE_OBJ: this->p_mem = malloc(sizeof(Json_Object)); if (this->p_mem != nullptr) - new (this->p_mem) Json_Object(*((Json_Object *)another.p_mem)); + { + new (this->p_mem) Json_Object(); + *((Json_Object *)this->p_mem) = *((Json_Object *)another.p_mem); + } break; case TYPE_NUM_INTEGER: this->p_mem = malloc(sizeof(int64_t)); @@ -507,12 +928,10 @@ Json_Value &Json_Value::operator=(const Json_Value &another) // 析构 Json_Value::~Json_Value() { - this->private_type = TYPE_NULL; - if (this->p_mem != nullptr) { // 对象析构 - switch (this->type) + switch (this->private_type) { case TYPE_STR: ((std::string *)p_mem)->~basic_string(); @@ -530,10 +949,11 @@ Json_Value::~Json_Value() // 释放内存 free(p_mem); } + this->private_type = TYPE_NULL; } // 作为直接值获取 -std::string Json_Value::asString(void) +std::string Json_Value::asString(void) const { if (this->type == TYPE_STR) return *(std::string *)this->p_mem; @@ -542,7 +962,7 @@ std::string Json_Value::asString(void) } // 作为 Json_Arry 获取 -Json_Arry Json_Value::asArry(void) +Json_Arry Json_Value::asArry(void) const { if (this->type == TYPE_ARRY) return *(Json_Arry *)this->p_mem; @@ -551,7 +971,7 @@ Json_Arry Json_Value::asArry(void) } // 作为 Json_Object 获取 -Json_Object Json_Value::asObject(void) +Json_Object Json_Value::asObject(void) const { if (this->type == TYPE_OBJ) return *(Json_Object *)this->p_mem; @@ -560,7 +980,7 @@ Json_Object Json_Value::asObject(void) } // 作为 int64 获取 -int64_t Json_Value::asInteger(void) +int64_t Json_Value::asInteger(void) const { if (this->type == TYPE_NUM_INTEGER) return *(int64_t *)this->p_mem; @@ -569,7 +989,7 @@ int64_t Json_Value::asInteger(void) } // 作为 double 获取 -double Json_Value::asFloat(void) +double Json_Value::asFloat(void) const { if (this->type == TYPE_NUM_FLOAT) return *(double *)this->p_mem; @@ -578,7 +998,7 @@ double Json_Value::asFloat(void) } // 作为 Boolean 逻辑值获取 -bool Json_Value::asBoolean(void) +bool Json_Value::asBoolean(void) const { if (this->type == TYPE_BOOLEAN) return *(bool *)this->p_mem; @@ -587,7 +1007,7 @@ bool Json_Value::asBoolean(void) } // 是否为空 -bool Json_Value::isNull(void) +bool Json_Value::isNull(void) const { return (this->private_type == TYPE_NULL); } @@ -614,7 +1034,7 @@ Json_Pair &Json_Pair::operator=(const Json_Pair &another) } // 空判定 -bool Json_Pair::isNull() +bool Json_Pair::isNull() const { return this->Null_Flag; } @@ -633,13 +1053,13 @@ Json_Arry &Json_Arry::operator=(const Json_Arry &another) } // 获取元素大小 -size_t Json_Arry::size(void) +size_t Json_Arry::size(void) const { return this->private_element_list.size(); } // 数组索引重载 -Json_Value Json_Arry::operator[](size_t index) +Json_Value Json_Arry::operator[](size_t index) const { if (index < this->private_element_list.size()) return this->private_element_list[index]; @@ -648,7 +1068,7 @@ Json_Value Json_Arry::operator[](size_t index) } // 是否为空 -bool Json_Arry::isNull(void) +bool Json_Arry::isNull(void) const { return (this->private_element_list.size() == 0); } @@ -667,13 +1087,13 @@ Json_Object &Json_Object::operator=(const Json_Object &another) } // 获取元素大小 -size_t Json_Object::size(void) +size_t Json_Object::size(void) const { return this->private_element_list.size(); } // 数组索引重载 -Json_Pair Json_Object::operator[](size_t index) +Json_Pair Json_Object::operator[](size_t index) const { if (index < this->private_element_list.size()) return this->private_element_list[index]; @@ -682,7 +1102,7 @@ Json_Pair Json_Object::operator[](size_t index) } // 由Key 查找值 -Json_Value Json_Object::get(std::string key) +Json_Value Json_Object::get(std::string key) const { for (auto pair : this->private_element_list) if (pair.key == key) @@ -692,7 +1112,7 @@ Json_Value Json_Object::get(std::string key) } // 是否为空 -bool Json_Object::isNull(void) +bool Json_Object::isNull(void) const { return (this->private_element_list.size() == 0); } \ No newline at end of file