答案:本文介绍如何用C++从零实现一个简单的JSON解析器,核心是定义支持null、boolean、number、string、array和object的JsonValue类型,使用std::variant存储不同类型,并通过递归下降解析法为每种类型编写解析函数,最终组合成完整解析器。代码包含数据结构定义、解析逻辑和测试示例,适合理解JSON结构与编译原理基础。

想用C++从零实现一个简单的JSON解析器?关键在于理解JSON的结构和递归下降的基本思路。JSON支持几种基本类型:null、boolean、number、string、array 和 object,我们可以为每种类型写一个解析函数,通过递归组合起来。整个过程不需要复杂的工具,纯手工编写即可。
1. 定义JSON数据结构
首先,我们需要一个能表示任意JSON值的C++类型。使用 std::variant 是个好选择,它能安全地存储不同类型的数据。
#include #include #include
};
2. 实现递归下降解析器
我们定义一个解析器类,维护当前解析位置和输入字符串。每个JSON类型对应一个解析函数。
立即学习“C++免费学习笔记(深入)”;
class JsonParser {private: const std::string& input; size_t pos;// 跳过空白字符void skip_whitespace() { while (pos < input.size() && (input[pos] == ' ' || input[pos] == '' || input[pos] == '' || input[pos] == '')) ++pos;}// 匹配并消耗指定字符bool match(char c) { skip_whitespace(); if (pos < input.size() && input[pos] == c) { ++pos; return true; } return false;}// 解析 "null"JsonValue parse_null() { if (input.substr(pos, 4) == "null") { pos += 4; return JsonValue(nullptr); } throw std::runtime_error("Expected 'null'");}// 解析 "true" / "false"JsonValue parse_boolean() { if (input.substr(pos, 4) == "true") { pos += 4; return JsonValue(true); } if (input.substr(pos, 5) == "false") { pos += 5; return JsonValue(false); } throw std::runtime_error("Expected 'true' or 'false'");}// 解析数字(简单版本,支持整数和小数)JsonValue parse_number() { size_t start = pos; if (pos < input.size() && input[pos] == '-') ++pos; if (pos == input.size() || !isdigit(input[pos])) throw std::runtime_error("Invalid number"); while (pos < input.size() && isdigit(input[pos])) ++pos; if (pos < input.size() && input[pos] == '.') { ++pos; if (pos == input.size() || !isdigit(input[pos])) throw std::runtime_error("Invalid number"); while (pos < input.size() && isdigit(input[pos])) ++pos; } std::string numStr = input.substr(start, pos - start); try { return JsonValue(std::stod(numStr)); } catch (...) { throw std::runtime_error("Invalid number format"); }}// 解析带引号的字符串(未处理转义字符)JsonValue parse_string() { if (!match('"')) throw std::runtime_error("Expected '"'"); size_t start = pos; while (pos = input.size()) throw std::runtime_error("Unexpected end of input"); char c = input[pos]; if (c == 'n') return parse_null(); if (c == 't' || c == 'f') return parse_boolean(); if (c == '-' || isdigit(c)) return parse_number(); if (c == '"') return parse_string(); if (c == '[') return parse_array(); if (c == '{') return parse_object(); throw std::runtime_error("Unexpected character: " + std::string(1, c));}
public:explicit JsonParser(const std::string& str) : input(str), pos(0) {}
JsonValue parse() { JsonValue result = parse_value(); skip_whitespace(); if (pos != input.size()) throw std::runtime_error("Extra characters after JSON"); return result;}
};
3. 使用示例
写个简单的main函数测试一下:
立即学习“C++免费学习笔记(深入)”;
#include #includevoid print_json(const JsonValue& val, int indent = 0) {std::string space(indent, ' ');if (val.is_null()) {std::cout << "null";} else if (val.is_bool()) {std::cout << (val.as_bool() ? "true" : "false");} else if (val.is_number()) {std::cout << val.as_number();} else if (val.is_string()) {std::cout << """ << val.as_string() << """;} else if (val.is_array()) {std::cout << "[";const auto& arr = val.as_array();for (size_t i = 0; i < arr.size(); ++i) {std::cout << std::string(indent + 2, ' ');print_json(arr[i], indent + 2);if (i != arr.size() - 1) std::cout << ",";std::cout << "";}std::cout << std::string(indent, ' ') << "]";} else if (val.is_object()) {std::cout << "{";const auto& obj = val.as_object();auto it = obj.begin();while (it != obj.end()) {std::cout << std::string(indent + 2, ' ') << """ <first <second, indent + 2);++it;if (it != obj.end()) std::cout << ",";std::cout << "";}std::cout << std::string(indent, ' ') << "}";}}
int main() {std::string json_str = R"({"name": "Alice","age": 30,"is_student": false,"grades": [85.5, 92.0, 78.5],"address": {"city": "Beijing","zipcode": "100000"},"spouse": null})";
try { JsonParser parser(json_str); JsonValue root = parser.parse(); print_json(root); std::cout << std::endl;} catch (const std::exception& e) { std::cerr << "Parse error: " << e.what() << std::endl; return 1;}return 0;
}
4. 注意事项与改进方向
这个解析器是教学级的,但已具备核心功能。你可以在此基础上扩展:
支持字符串中的转义字符(如 , ", )支持科学计数法(如 1e5)添加位置信息便于报错定位实现序列化(将 JsonValue 转回字符串)优化性能,避免 substr 频繁拷贝
基本上就这些。递归下降的关键是“一个函数管一种语法结构”,逻辑清晰,容易调试。自己写一遍,对理解JSON和编译原理都很有帮助。
以上就是C++如何实现一个简单的JSON解析器_从零开始编写C++递归下降JSON解析器的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1486947.html
微信扫一扫
支付宝扫一扫