object库,提供运行时对象支持,通过引用计数维护所有对象。只要是继承自tb_object_t的对象类型都是可以经过扩展实现序列化和反序列化。
库内部也已经提供了常用的对象类型:
tb_object_data_t: 数据对象类型
tb_object_date_t: 日期对象类型
tb_object_null_t: 空值对象类型
tb_object_array_t: 数组对象类型
tb_object_string_t: 字符串对象类型
tb_object_number_t: 数值对象类型,包括浮点、整型
tb_object_boolean_t: 布尔对象类型
tb_object_dictionary_t: 字典对象类型
可以看到,基本上这些对象已经可以进行常用数据维护了,和apple的CoreFoundation内部的常用对象很类似,而且可以很方便的扩展其他自定义类型的序列化,这部分等以后再细讲吧。。。
现在先简单看下如何快速解析一个json文件到内存:
- // 从文件读取json数据到内存,json_root为整个根对象
- tb_object_ref_t json_root = tb_object_read_from_url("/home/file/json.txt");
- // 从http读取json数据到内存,json_root为整个根对象
- // tb_object_ref_t json_root = tb_object_read_from_url("http://localhost/file/json.txt");
- // 从数据读取json数据到内存,json_root为整个根对象
- // tb_object_ref_t json_root = tb_object_read_from_data(data, size);
- // 从stream读取json数据到内存,json_root为整个根对象
- // tb_object_ref_t json_root = tb_object_read(stream);
- if (json_root)
- {
- // 将json_root的所有数据格式打印到终端,一般调试使用
- tb_object_dump(json_root);
- // 释放json_root对象,object跟CoreFoundation一样是有引用计数的
- // 这里json_root没有被其他引用,所以会被立马释放掉
- tb_object_exit(json_root);
- }
怎么样简单吧,如果要解析plist文件, 也是类似,只需换成plist 文件的url就行了 库内部回去自动检测文件格式,进行相应地解析工作,上层都是通用的object对象树 并且可以支持xplist(xml格式)、bplist(二进制格式)两种格式。
tb_object_ref_t plist_root = tb_object_read_from_url("/home/file/file.plist");
对于序列化到文件,也很简单:
- // 序列化json object到文件, size 为实际序列化的字节数,如果失败,返回:-1
- // 默认格式存储,通过 tab 和 换行 进行了格式化,方便查看
- tb_long_t size = tb_object_writ_to_url(object, "/home/file/json.txt", TB_OBJECT_FORMAT_JSON);
- // 序列化json object到文件, size 为实际序列化的字节数,如果失败,返回:-1
- // 并且压缩存储,去掉冗余的空白字符
- tb_long_t size = tb_object_writ_to_url(object, "/home/file/json.txt", TB_OBJECT_FORMAT_JSON | TB_OBJECT_FORMAT_DEFLATE);
- // 序列化json object到数据buffer,size 为实际序列化的字节数,如果失败,返回:-1
- tb_byte_t data[8192] = {0};
- tb_long_t size = tb_object_writ_to_data(object, data, 8192, TB_OBJECT_FORMAT_JSON);
其他格式类似,如下是可以支持的序列化格式:
- TB_OBJECT_FORMAT_BIN:tbox内部二进制序列化格式,最为节省空间,并且对字符串做了些简单的加密,可以扩展自定义的数据类型
- TB_OBJECT_FORMAT_BPLIST:apple的二进制plist格式,内部字符串为明文,并且空间利用率不是很高
- TB_OBJECT_FORMAT_XPLIST:apple的xml文本plist格式
- TB_OBJECT_FORMAT_XML:tbox内部的xml文本序列化格式,可以扩展自定义的数据类型
- TB_OBJECT_FORMAT_JSON:json序列化格式
object对象的字段解析有两种模式,一种是一层层迭代遍历,一种是直接定位到指定字段 迭代遍历,只有array和dictionay需要,他们同样是支持tbox容器库的迭代器模式的,例如:
- // 遍历array
- tb_for_all (tb_object_ref_t, item, tb_object_array_itor(array))
- {
- if (item)
- {
- // ...
- }
- }
- // 遍历dictionary
- tb_for_all (tb_object_dictionary_item_t*, item, tb_object_dictionary_itor(dictionary))
- {
- // 获取dictionary的每一个键值对
- if (item)
- {
- // 键名字符串
- tb_char_t const* key = item->key;
- // 值对象, 可以继续迭代下层或直接取值
- tb_object_ref_t val = item->val;
- // ...
- }
- }
如果要直接定位某个字段,可以使用tbox的seek模式,支持自定义路径格式:
- /* 例如对于这个xml的数据解析
- <dict>
- <key>string</key>
- <string>hello wolrd!</string>
- <key>com.xxx.xxx</key>
- <string>hello wolrd!</string>
- <key>integer</key>
- <number>31415926</number>
- <key>array</key>
- <array>
- <string>hello wolrd!</string>
- <number>31415926</number>
- <number>3.1415926</number>
- <false/>
- <true/>
- <dict>
- <key>string</key>
- <string>hello wolrd!</string>
- </dict>
- </array>
- </dict>
- * 其对应的字段路径:
- * 1. ".string" : hello wolrd!
- * 2. ".array[1]" : 31415926
- * 3. ".array[5].string" : hello wolrd!
- * 4. ".com\\.xxx\\.xxx" : hello wolrd!
- */
- /* seek到指定路径:.array[5].string ,进行解析字段
- *
- * 这里传TB_OBJECT_TYPE_STRING作为最后一个参数,是为了内部做一次类型检测
- * 如果这个字段确实string类型的,才会返回对象,否则返回null,这样上层解析代码
- * 看上去更加的简洁,不需要每次解析一个字段,都要外面做一下检测类型
- *
- * 如果传TB_OBJECT_TYPE_NONE进去,那么不管是不是string对象,都会返回成功
- * 这个时候上层如果不做类型检测,只是去字符串,库内部会有断言,但是不影响程序逻辑
- * 仅仅是提示下,你现在的处理类型有误。
- */
- tb_object_ref_t object = tb_object_seek(object, ".array[5].string", TB_OBJECT_TYPE_STRING);
- if (object)
- {
- tb_trace_d("%s", tb_object_string_cstr(object));
- }
其他字段的解析:
- /* 解析string类型字段, 取值前,先做类型判断是最安全的方式
- * 虽然直接转换也是安全的,类型不对内部直接会返回tb_null
- * 但是为了养成良好的编程习惯,在调试模式下,库内部会有检测断言提示类型不匹配
- */
- if (tb_object_type(object) == TB_OBJECT_TYPE_STRING)
- {
- tb_char_t const* string = tb_object_string_cstr(object);
- }
- // 解析number类型字段
- if (tb_object_type(object) == TB_OBJECT_TYPE_NUMBER)
- {
- // 获取整型值,如果不是会自动强转,有可能丢失精度
- tb_uint32_t value = tb_object_number_uint32(object);
- // 获取浮点值,如果不是会自动强转
- // tb_float_t value = tb_object_number_float(object);
- // 获取双精度浮点值,如果不是会自动强转
- // tb_double_t value = tb_object_number_double(object);
- }
- // 解析boolean类型字段
- if (tb_object_type(object) == TB_OBJECT_TYPE_BOOLEAN)
- {
- // 获取bool值
- tb_bool_t value = tb_object_boolean_bool(object);
- }
- // 解析data类型字段
- if (tb_object_type(object) == TB_OBJECT_TYPE_DATA)
- {
- // 获取数据指针
- tb_byte_t* data = tb_object_data_getp(object);
- // 获取数据大小
- tb_size_t size = tb_object_data_size(object);
- }
- // 解析date类型字段
- if (tb_object_type(object) == TB_OBJECT_TYPE_DATE)
- {
- // 获取时间戳
- tb_time_t time = tb_object_date_time(object);
- }
- // 解析array类型字段
- if (tb_object_type(object) == TB_OBJECT_TYPE_ARRAY)
- {
- // 获取成员数量
- tb_size_t count = tb_object_array_size(object);
- tb_size_t i = 0;
- for (i = 0; i < count; i++)
- {
- tb_object_ref_t item = tb_object_array_item(object, i);
- }
- }
- // 解析dictionary类型字段
- if (tb_object_type(object) == TB_OBJECT_TYPE_DICTIONARY)
- {
- // 获取对象键值
- tb_object_ref_t value = tb_object_dictionary_val(object, "key_name");
- }