lept_json的学习之parse_object

lept_json学习之parse_object

这一节讲parse_object

数据结构

JSON的Object 是以键值对的方式存储的。
{ key:value}这里我们默认key为JSON字符串。
要表示键值对的集合,数据结构有很多种:

  1. 动态数组(dynamic array):可扩展容量的数组,如 C++ 的 std::vector。
  2. 有序动态数组(sorted dynamic array):和动态数组相同,但保证元素已排序,可用二分搜寻查询成员。
  3. 平衡树(balanced tree):平衡二叉树可有序地遍历成员,如红黑树和 C++ 的 std::map(std::multi_map 支持重复键)。
  4. 哈希表(hash table):通过哈希函数能实现平均 O(1) 查询,如 C++11 的 std::unordered_map(unordered_multimap 支持重复键)。

设一个对象有 n 个成员,数据结构的容量是 m,n ⩽ m,那么一些常用操作的时间/空间复杂度如下:

动态数组 有序动态数组 平衡树 哈希表
有序
自定成员次序
初始化 n 个成员 O(n) O(n log n) O(n log n) 平均 O(n)、最坏 O(n^2)
加入成员 分摊 O(1) O(n) O(log n) 平均 O(1)、最坏 O(n)
移除成员 O(n) O(n) O(log n) 平均 O(1)、最坏 O(n)
查询成员 O(n) O(log n) O(log n) 平均 O(1)、最坏 O(n)
遍历成员 O(n) O(n) O(n) O(m)
检测对象相等 O(n^2) O(n) O(n) 平均 O(n)、最坏 O(n^2)
空间 O(m) O(m) O(n) O(m)

为了简单起见,我们的 leptjson 选择用动态数组的方案。

因为object用的数据结构也是动态数组,就导致了object和array非常的相像,基本唯一的区别就只有键值对了。

typedef struct lept_value lept_value;//前向声明
typedef struct lept_member lept_member;

struct lept_value{
   
	//我们可使用 C 语言的 union 来节省内存:
	union{
   
		struct {
    lept_member* m; size_t size,capacity; }m_obj;
		struct {
    lept_value* e;  size_t size,capacity; }m_arr;/* array */
		struct  {
    char* s; size_t len; }m_str;      /* string */
		double m_num;                               /* number */
	}u;
	lept_type type;
};

struct lept_member {
   
	char* k; size_t klen;   /* member key string, key string length */
	lept_value v;           /* member value */
};

Parse_object

还记得我之前在string类时提到,string_parse里有一个string_parse_raw是后期object 在parse key值时重构得到的。那么就是在这里了。
{key :value,key:value}
我们在解析object时,左花括号({)确认是object,而后解析空白,解析键值,解析冒号,解析value,有逗号解析逗号,没有逗号解析右花括号,最后解析完毕,把整个object值给copy过去。
在内存分配上的操作和array几乎一样。

static int lept_parse_object(lept_context& c, lept_value& v) {
   
	size_t size;
	lept_member m;//创建一个member
	int ret;//需要返回的object解析状态flag
	EXPECT(c, '{');//确定第一个字符为{右花括号
	lept_parse_whitespace(c);//解析空白
	if (*c.json == '}') {
   //空对象
		c.json++;
		v.type = LEPT_OBJECT;
		v.u.m_obj.m = 0;
		v.u.m_obj.size = 0;
		return LEPT_PARSE_OK;
	}
	m.k = NULL;//member key置空
	size = 0;//size 置零
	for (;;) {
   
		char* str;  //创建一个临时字符串
		lept_init(m.v);//初始化member value值
		/* 1. parse key */
		if (*c.json != '"') {
   //如果key值不是由"开头,则解析错误
			ret = LEPT_PARSE_MISS_KEY;
			break;
		}
		//如果key值解析不成功,退出循环
		if ((ret = lept_parse_string_raw(c, str, m.klen)) != LEPT_PARSE_OK)
			break;
			//解析成功则将解析得到的值copy给member key
		memcpy(m.k = (char*)malloc(m
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值