首页 > 后端开发 > C++ > 正文

C++如何实现一个简单的JSON解析器?C++递归下降解析法实战【项目练习】

穿越時空
发布: 2025-12-14 20:45:08
原创
766人浏览过
用C++11手写轻量级JSON解析器需采用递归下降法,为value、object、array等非终结符实现对应函数,配合JsonValue联合体结构和位置指针pos遍历字符串,正确处理转义、数字解析、空白跳过及错误定位。

"c++如何实现一个简单的json解析器?c++递归下降解析法实战【项目练习】"

用C++手写一个轻量级JSON解析器,核心是递归下降(Recursive Descent)——它天然契合JSON的嵌套结构(对象、数组可无限嵌套),逻辑清晰、易于理解和调试。不需要第三方库,纯标准C++11即可实现基础功能(字符串、数字、布尔、null、对象、数组)。

理解JSON语法与递归下降映射关系

JSON文本本质是上下文无关文法(CFG),递归下降就是为每个非终结符(如 valueobjectarray)写一个对应函数,函数内部按语法规则“向下”调用其他函数,形成自然的递归调用链。

关键文法规则(简化版):

  • valuestring | number | object | array | true | false | null
  • object{ [ member ( , member )* ] }
  • memberstring : value
  • array[ [ value ( , value )* ] ]

每个规则直接对应一个解析函数,比如 parse_value() 调用 parse_object()parse_array(),后者再递归调用 parse_value() —— 这就是“下降”和“递归”的由来。

立即学习C++免费学习笔记(深入)”;

设计核心数据结构:JsonValue

先定义一个能容纳所有JSON类型的联合体式容器(用 std::variant 或手动管理):

"Musho"
Musho

AI网页设计Figma插件

"Musho" 76
查看详情 "Musho"
struct JsonValue {
    enum Type { STRING, NUMBER, OBJECT, ARRAY, BOOL, NULL_T };
    Type type;
    std::string str;           // for STRING
    double num;                // for NUMBER
    bool boolean;              // for BOOL
    std::map<std::string, JsonValue> obj;   // for OBJECT
    std::vector<JsonValue> arr;             // for ARRAY
};
登录后复制

注意:NULL_T 可用特殊标记(如 num = NAN)或额外 bool is_null 字段;实际项目中推荐用 std::optionalstd::variant<:monostate ...></:monostate> 更安全。

实现解析器骨架与关键函数

维护一个位置指针 pos 遍历输入字符串,跳过空白,按首字符分发:

  • 遇到 " → 调用 parse_string()(需处理转义,如 "\
  • 遇到 { → 调用 parse_object()(读 {,循环解析 "key": value,直到 }
  • 遇到 [ → 调用 parse_array()(读 [,循环解析 value,直到 ]
  • 遇到 t / f / n → 分别识别 truefalsenull
  • 遇到数字或负号 → 调用 parse_number()(支持整数、小数、科学计数法,可用 std::stod 或手动解析)

所有函数都接受并更新引用参数 size_t& pos,失败时抛异常或返回 std::nullopt(建议用异常,便于定位错误位置)。

实战要点与易错提醒

递归下降不是“写完就跑”,几个关键细节决定成败:

  • 跳空白必须统一:写一个 skip_whitespace(const std::string& s, size_t& pos),所有解析函数开头必调用
  • 字符串解析要小心:逐字符读,遇 " 结束;中间遇 就取下一个字符,按规则转义(\, "", →换行符等)
  • 数字解析别依赖 atof:它不检查非法尾部(如 "123abc" 会成功解析为123),应手动扫描合法数字字符后截取子串再转换
  • 错误提示要带位置:抛异常时附上 pos,比如 throw std::runtime_error("Expected ',' or '}' at " + std::to_string(pos));
  • 避免深递归爆:JSON嵌套过深(>1000层)可能栈溢出,生产环境需加深度限制(传入 max_depth 参数)

基本上就这些。写完后用典型用例测试:{"name":"Alice","scores":[95,87],"active":true}、空对象 {}、嵌套 {"a":{"b":[1,2]}}、非法输入(缺引号、逗号错位)看是否报错准确。不复杂但容易忽略边界,多测几遍就稳了。

以上就是C++如何实现一个简单的JSON解析器?C++递归下降解析法实战【项目练习】的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号