欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 高考 > JsonCpp源码分析——Reader

JsonCpp源码分析——Reader

2025/11/11 23:38:03 来源:https://blog.csdn.net/xiaoan08133192/article/details/142111944  浏览:    关键词:JsonCpp源码分析——Reader

1、与Writer模块功能相反,可以将Reader理解成一个反序列化的工具,Writer的作用主要是将Value对象转成string或者流式的结构,Reader的作用主要是将流式的结构转成Value类型的对象。Reader类的主要职责有3个,解析 JSON 字符串:将 JSON 格式的字符串读取并解析成相应的 C++ 数据结构。处理不同的数据类型,支持解析 JSON 对象、数组、字符串、数字、布尔值和 null。处理错误,在解析过程中,如果遇到格式错误或不符合 JSON 标准的情况,Reader 类能够捕获这些错误并提供相关的错误信息。示例代码如下:

#include <json/json.h>
#include <iostream>
#include <string>int main() {std::string jsonString = R"({"name": "Alice", "age": 30, "is_student": false})";Json::CharReaderBuilder readerBuilder;Json::Value root;std::istringstream jsonStream(jsonString);std::string errs;// 解析 JSON 字符串if (Json::parseFromStream(readerBuilder, jsonStream, &root, &errs)) {std::cout << "Name: " << root["name"].asString() << std::endl;std::cout << "Age: " << root["age"].asInt() << std::endl;std::cout << "Is Student: " << root["is_student"].asBool() << std::endl;} else {std::cerr << "Error parsing JSON: " << errs << std::endl;}return 0;
}

下面这个接口是实际开发中经常会用到的接口,当然我可以也可以向StreamWriterBuilder那样设置解析的属性,这个不难,不再进行介绍,后面会详细介绍下实现解析功能的精髓Token的设计。
bool JSON_API parseFromStream(CharReader::Factory const&, IStream&, Value* root,
String* errs);
2、Token是Reader模块中的精髓,它是jsoncpp 库中用于表示 JSON 数据流中各个组成部分的类。在 JSON 数据解析的过程中,Token 代表了 JSON 字符串中的基本元素,如对象的开始、数组的结束、字符串、数字等。通过对这些标记的处理,jsoncpp 能够逐步解析 JSON 数据并将其转换为 C++ 数据结构。Token的定义如下:

  enum TokenType {tokenEndOfStream = 0,     //数据流的结束tokenObjectBegin,         //对象的开始 {tokenObjectEnd,           //对象的结束 }tokenArrayBegin,          //数组的开始 [tokenArrayEnd,            //数组的结束 ]tokenString,              // stringtokenNumber,tokenTrue,tokenFalse,tokenNull,tokenArraySeparator,      //数组元素分隔符 ,tokenMemberSeparator,     // 对象成员分隔符 ,tokenComment,             // 注释tokenError                // 解析出错};class Token {public:TokenType type_;Location start_;Location end_;// start_ 表示标记的开始位置,end_ 表示标记的结束位置,识别出TokenType会根据这两个指针去解析对应的数据};

我觉着在解析Object时可以帮助理解Token的作用

bool Reader::readObject(Token& token) {Token tokenName;String name;Value init(objectValue);  // 创建一个对象类型的初始值currentValue().swapPayload(init);  // 将当前值设置为初始化的对象值currentValue().setOffsetStart(token.start_ - begin_);  // 设置对象的起始位置while (readToken(tokenName)) {  // 读取下一个标记bool initialTokenOk = true;// 跳过可能存在的注释while (tokenName.type_ == tokenComment && initialTokenOk)initialTokenOk = readToken(tokenName);if (!initialTokenOk)break;  // 如果读取注释失败,则退出循环// 如果遇到对象结束标记且没有名称,则表示对象为空if (tokenName.type_ == tokenObjectEnd && name.empty())return true;name.clear();  // 清除之前的名称// 处理对象的成员名称if (tokenName.type_ == tokenString) {if (!decodeString(tokenName, name))  // 解析字符串名称return recoverFromError(tokenObjectEnd);  // 解析错误,恢复错误处理} else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {Value numberName;if (!decodeNumber(tokenName, numberName))  // 解析数字名称return recoverFromError(tokenObjectEnd);  // 解析错误,恢复错误处理name = numberName.asString();  // 将数字转换为字符串作为名称} else {break;  // 如果名称不是字符串或数字,则退出循环}Token colon;// 读取冒号,检查是否存在冒号分隔符if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {return addErrorAndRecover("Missing ':' after object member name", colon, tokenObjectEnd);  // 如果缺少冒号,记录错误并恢复}Value& value = currentValue()[name];  // 获取当前值的对应成员nodes_.push(&value);  // 将成员值推入栈中bool ok = readValue();  // 读取成员的值nodes_.pop();  // 从栈中弹出成员值if (!ok)  // 如果读取值失败,错误已设置return recoverFromError(tokenObjectEnd);Token comma;// 读取逗号或对象结束标记,检查是否存在有效的分隔符if (!readToken(comma) ||(comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&comma.type_ != tokenComment)) {return addErrorAndRecover("Missing ',' or '}' in object declaration", comma, tokenObjectEnd);  // 如果缺少逗号或结束标记,记录错误并恢复}bool finalizeTokenOk = true;// 跳过可能存在的注释while (comma.type_ == tokenComment && finalizeTokenOk)finalizeTokenOk = readToken(comma);if (comma.type_ == tokenObjectEnd)return true;  // 如果遇到对象结束标记,则成功解析对象并返回}return addErrorAndRecover("Missing '}' or object member name", tokenName, tokenObjectEnd);  // 如果缺少对象结束标记或成员名称,记录错误并恢复
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词