#include "json_utils.h" #include std::string json_trim(const std::string& s) { size_t b = s.find_first_not_of(" \t\r\n"); if (b == std::string::npos) return ""; size_t e = s.find_last_not_of(" \t\r\n"); return s.substr(b, e - b + 1); } static bool is_ws(char c) { return c == ' ' || c == '\t' || c == '\r' || c == '\n'; } std::string json_get_raw(const std::string& text, const std::string& key) { std::string k = "\"" + key + "\""; size_t pos = 0; while ((pos = text.find(k, pos)) != std::string::npos) { bool key_ok = true; if (pos > 0) { char c = text[pos - 1]; if (isalnum((unsigned char)c) || c == '_') key_ok = false; } if (key_ok) { size_t p = pos + k.size(); while (p < text.size() && is_ws(text[p])) ++p; // 跳过空白 if (p >= text.size()) return ""; if (text[p] != ':') { pos = pos + 1; continue; } ++p; while (p < text.size() && is_ws(text[p])) ++p; // 跳过冒号后空白 if (p >= text.size()) return ""; char c = text[p]; if (c == '"') { // 字符串:读到配对引号 size_t q = p + 1; while (q < text.size() && text[q] != '"') ++q; return text.substr(p, q - p + 1); } else if (c == '{' || c == '[') { char close = (c == '{') ? '}' : ']'; int depth = 0; size_t q = p; for (; q < text.size(); ++q) { if (text[q] == '"') { ++q; while (q < text.size() && text[q] != '"') ++q; } else if (text[q] == c) ++depth; else if (text[q] == close) { --depth; if (depth == 0) { ++q; break; } } } return text.substr(p, q - p); } else { // 数字 / true / false / null size_t q = p; while (q < text.size() && text[q] != ',' && text[q] != '}' && text[q] != ']' && !is_ws(text[q])) ++q; return text.substr(p, q - p); } } pos = pos + 1; } return ""; } static std::string unquote(const std::string& raw) { std::string t = json_trim(raw); if (t.size() >= 2 && t[0] == '"' && t[t.size() - 1] == '"') return t.substr(1, t.size() - 2); return t; } bool json_get_string(const std::string& text, const std::string& key, std::string& out) { std::string raw = json_get_raw(text, key); if (raw.empty()) return false; out = unquote(raw); return true; } bool json_get_number(const std::string& text, const std::string& key, double& out) { std::string raw = json_get_raw(text, key); if (raw.empty()) return false; std::string t = json_trim(raw); if (t.empty()) return false; try { out = std::stod(t); return true; } catch (...) { return false; } } bool json_get_bool(const std::string& text, const std::string& key, bool& out) { std::string raw = json_get_raw(text, key); if (raw.empty()) return false; std::string t = json_trim(raw); if (t == "true") { out = true; return true; } if (t == "false") { out = false; return true; } double d; if (json_get_number(text, key, d)) { out = (d != 0); return true; } return false; } int json_get_point_array(const std::string& text, const std::string& key, std::vector>& out) { std::string raw = json_get_raw(text, key); if (raw.empty()) return 0; std::string t = json_trim(raw); if (t.empty() || t[0] != '[') return 0; // 逐个匹配 "[数,数]" 子元素 size_t i = 1; int cnt = 0; while (i < t.size()) { size_t l = t.find('[', i); if (l == std::string::npos) break; size_t r = t.find(']', l); if (r == std::string::npos) break; std::string ele = t.substr(l + 1, r - l - 1); size_t comma = ele.find(','); if (comma != std::string::npos) { try { double a = std::stod(json_trim(ele.substr(0, comma))); double b = std::stod(json_trim(ele.substr(comma + 1))); out.push_back(std::make_pair(a, b)); ++cnt; } catch (...) {} } i = r + 1; } return cnt; } // ---- 枚举对象一级键名 ---- // 逐字符扫描,跟踪字符串与嵌套深度,只收集 depth==1 的键名。 std::vector json_object_keys(const std::string& text, const std::string& group) { std::string obj = group.empty() ? text : json_get_raw(text, group); std::vector keys; size_t p = obj.find('{'); if (p == std::string::npos) return keys; int depth = 0; bool in_str = false; bool esc = false; for (size_t i = p; i < obj.size(); ++i) { char c = obj[i]; if (in_str) { if (esc) { esc = false; continue; } if (c == '\\') { esc = true; continue; } if (c == '"') in_str = false; continue; } if (c == '"') { // 字符串开始:若当前在对象层(depth>=1)且前一个非空白字符不是 ':' 或 ',', // 则它是键名;否则是值(值已在 json_get_raw 中处理,这里跳过)。 size_t j = i + 1; size_t q = obj.find('"', j); while (q != std::string::npos && obj[q - 1] == '\\') q = obj.find('"', q + 1); if (q == std::string::npos) break; std::string tok = obj.substr(j, q - j); size_t k = i; while (k > p && is_ws(obj[k - 1])) --k; char prev = (k > p) ? obj[k - 1] : '{'; if (depth == 1 && (prev == '{' || prev == ',')) keys.push_back(tok); i = q; // 已整体消费该字符串(键或值),继续下一个字符 continue; } if (c == '{' || c == '[') { ++depth; continue; } if (c == '}' || c == ']') { --depth; if (depth <= 0) break; continue; } } return keys; } std::vector json_object_keys(const std::string& text) { return json_object_keys(text, ""); } // ---- 分组两级查找实现 ---- std::string json_get_raw(const std::string& text, const std::string& group, const std::string& key) { std::string obj = group.empty() ? text : json_get_raw(text, group); if (obj.empty()) return ""; return json_get_raw(obj, key); } bool json_get_string(const std::string& text, const std::string& group, const std::string& key, std::string& out) { std::string raw = json_get_raw(text, group, key); if (raw.empty()) return false; out = unquote(raw); return true; } bool json_get_number(const std::string& text, const std::string& group, const std::string& key, double& out) { std::string raw = json_get_raw(text, group, key); if (raw.empty()) return false; std::string t = json_trim(raw); if (t.empty()) return false; try { out = std::stod(t); return true; } catch (...) { return false; } } bool json_get_bool(const std::string& text, const std::string& group, const std::string& key, bool& out) { std::string raw = json_get_raw(text, group, key); if (raw.empty()) return false; std::string t = json_trim(raw); if (t == "true") { out = true; return true; } if (t == "false") { out = false; return true; } double d; if (json_get_number(text, group, key, d)) { out = (d != 0); return true; } return false; } int json_get_point_array(const std::string& text, const std::string& group, const std::string& key, std::vector>& out) { std::string raw = json_get_raw(text, group, key); if (raw.empty()) return 0; std::string t = json_trim(raw); if (t.empty() || t[0] != '[') return 0; // 逐个匹配 "[数,数]" 子元素 size_t i = 1; int cnt = 0; while (i < t.size()) { size_t l = t.find('[', i); if (l == std::string::npos) break; size_t r = t.find(']', l); if (r == std::string::npos) break; std::string ele = t.substr(l + 1, r - l - 1); size_t comma = ele.find(','); if (comma != std::string::npos) { try { double a = std::stod(json_trim(ele.substr(0, comma))); double b = std::stod(json_trim(ele.substr(comma + 1))); out.push_back(std::make_pair(a, b)); ++cnt; } catch (...) {} } i = r + 1; } return cnt; }