IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发测试 -> c++手写一个json库 -> 正文阅读

[开发测试]c++手写一个json库

json 关键原理简述

json可以是null,bool,int, double,string,array,object几个不同类型;

其中,array=vector<json>; object=map<string,json>;

所以 json 是一个多种子类的基类,代码中为 Value;

class Value
	{
	public:
		enum Type
		{
			NUL,
			INT,
			DOUBLE,
			BOOL,
			STRING,
			OBJECT,
			ARRAY,
		};

	public:
		Value(Type type)
			:type_(type)
		{

		}

		virtual std::pair<bool, int> IntValue() const
		{
			return std::make_pair(false, 0);
		}

		virtual std::pair<bool, double> DoubleValue() const
		{
			return std::make_pair(false, 0);
		}

		virtual std::pair<bool, bool> BoolValue() const
		{
			return std::make_pair(false, true);
		}

		virtual std::pair<bool, std::string> StrValue() const
		{
			return std::make_pair(false, "null string");
		}

		//virtual Object ObjectValue() const;
		
		//virtual Array ArrayValue() const ;

		virtual std::pair<bool, const Json& > at(const std::string& key) const;
		
		virtual std::pair<bool, const Json& > at(size_t i)const;

		virtual std::string GetRawStr() const=0;

		Type GetType()
		{
			return type_;
		}

	private:
		Type type_;
	};

value具有所有子类的基本函数,子类(null,bool,int, double,string,array,object)通过重写自己的函数,使得value的虚函数具有实际的意义,即返回正确的结果<true,value>。

value的子类是json类的数据成员,通过一层封装,消除不同json类型的构建的差异性,可以通过初始化列表,完成一个复杂json对象的构建。json类还提供解析字符串为json对象的功能,该功能也通过JsonParser对象外包出去。因此Json只是一层皮。

字符串解析为json的过程

字符串解析分为两种模式,一种是带有注释的json字符串解析,一种是无注释。整个解析过程是一个流水线式的解析,通过当前符号区分当前要解析的内容是什么。

Json Parse(int depth)
		{
			if (depth > max_depth) {
				return fail("exceeded maximum nesting depth");
			}

			char ch = GetNextToken();
			if (failed_)
				return Json();

			if (ch == '-' || (ch >= '0' && ch <= '9')) {
				i--;
				return ParseNumber();
			}

			if (ch == 't')
				return expect("true", true);

			if (ch == 'f')
				return expect("false", false);

			if (ch == 'n')
				return expect("null", Json());

			if (ch == '"')
				return ParseString();

			if (ch == '{') {
				Object data;
				ch = GetNextToken();
				if (ch == '}')
					return data;

				while (1) {
					if (ch != '"')
						//return fail("expected '\"' in object, got " + esc(ch));
						return fail("expected '\"' in object, got " + ch);
					std::string key = ParseString();
					if (failed_)
						return Json();

					ch = GetNextToken();
					if (ch != ':')
						//return fail("expected ':' in object, got " + esc(ch));
						return fail("expected ':' in object, got " + ch);

					data[std::move(key)] = Parse(depth + 1);
					if (failed_)
						return Json();

					ch = GetNextToken();
					if (ch == '}')
						break;
					if (ch != ',')
						//return fail("expected ',' in object, got " + esc(ch));
						return fail("expected ',' in object, got " + ch);

					ch = GetNextToken();
				}
				return data;
			}

			if (ch == '[') {
				Array data;
				ch = GetNextToken();
				if (ch == ']')
					return data;

				while (1) {
					i--;
					data.push_back(Parse(depth + 1));
					if (failed_)
						return Json();

					ch = GetNextToken();
					if (ch == ']')
						break;
					if (ch != ',')
						//return fail("expected ',' in list, got " + esc(ch));
						return fail("expected ',' in list, got " + ch);

					ch = GetNextToken();
					(void)ch;
				}
				return data;
			}

			//return fail("expected value, got " + esc(ch));
			return fail("expected value, got " + ch);
		}

主要部分object和array类型的解析都是递归的过程。

关键函数解析

解析过程中出现错误怎么处理?

        Json fail(std::string&& msg) {
			return fail(move(msg), Json());
		}

		template <typename T>
		T fail(std::string&& msg, const T err_ret) {
			if (!failed_)
				err_ = std::move(msg);
			failed_ = true;
			return err_ret;
		}

解析过程中出现错误往往要返回一个值,用户通过返回值判断该解析过程或者子解析过程是否出现错误。这是json11处理方式,通过模板可以返回不同的类型满足各部分解析返回值需求,并且生成错误信息。

解析特定类型的函数抽象

Json expect(const std::string& expected, Json res) {
			if (i == 0)
			{
				return fail("expect wrong i(position of str_)", Json());
			}
			i--;
			if (str_.compare(i, expected.length(), expected) == 0) {
				i += expected.length();
				return res;
			}
			else {
				return fail("parse error: expected " + expected + ", got " + str_.substr(i, expected.length()));
			}
		}

在对bool和null类型解析是一个类似的过程,采用expect()进行抽象,一个string对应一个json对象。

json对象字符串的输出

不同json类型有不同的字符串输出方式,并且和解析一样存在递归调用如果都放到自己的成员函数下,递归调用就成问题。因此将字符串输出代理给RawStr类。RawStr具有一系列static的GetRawStr()函数,彼此间相互调用。

另一种还是将字符串输出放到各类型内部,递归调用时,通过构建临时Json对象,递归调用获取json字符串的函数。

参考

大部分源码来源于json11,进行了自己的阅读理解,用简单的方式组合在一起,并去除了编码相关的模块,不考虑编码的问题。

源码

  开发测试 最新文章
pytest系列——allure之生成测试报告(Wind
某大厂软件测试岗一面笔试题+二面问答题面试
iperf 学习笔记
关于Python中使用selenium八大定位方法
【软件测试】为什么提升不了?8年测试总结再
软件测试复习
PHP笔记-Smarty模板引擎的使用
C++Test使用入门
【Java】单元测试
Net core 3.x 获取客户端地址
上一篇文章      下一篇文章      查看所有文章
加:2022-03-22 20:54:32  更:2022-03-22 20:55:09 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/18 0:28:28-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码