如何使用libbson C API向已有bson_t数组追加文档/对象
正确追加BSON对象到BSON数组的方法
你遇到的核心问题是:BSON数组本质是**键为连续数字字符串("0","1","2"...)**的特殊文档,直接用bson_append_document会要求指定键,无法自动生成数组的索引键;而bson_concat是用于合并普通文档的键值对,不适合数组操作,强行使用会破坏数组的索引结构,导致后续解析异常。
高效实现方案
虽然bson_array_builder没有直接从现有BSON数组初始化的API,但利用bson_iter遍历原数组元素的方式效率并不低——bson_iter是libbson原生的高效遍历器,无额外序列化/反序列化开销,结合bson_array_builder_append_iter可以快速迁移原数组元素。具体步骤如下:
- 创建空的数组构建器,用于组装最终数组
- 遍历原BSON数组的所有元素,逐个追加到构建器
- 追加目标BSON对象到构建器
- 从构建器生成最终的BSON数组
- 释放所有临时资源
完整代码示例
#include <bson/bson.h> int main() { char* jsonObjStr = "{ \"Name\" : \"Obj_1\" }"; char* jsonArrayStr = "[ { \"Name\" : \"Obj_0\" } ]"; // 从JSON字符串解析出BSON对象和数组 bson_error_t error; bson_t* bsonObj = bson_new_from_json((const uint8_t*)jsonObjStr, -1, &error); if (!bsonObj) { fprintf(stderr, "解析对象失败: %s\n", error.message); return 1; } bson_t* bsonArray = bson_new_from_json((const uint8_t*)jsonArrayStr, -1, &error); if (!bsonArray) { fprintf(stderr, "解析数组失败: %s\n", error.message); bson_destroy(bsonObj); return 1; } // 1. 创建数组构建器 bson_array_builder_t bab; bson_array_builder_init(&bab, NULL); // 2. 遍历原数组,追加所有元素到构建器 bson_iter_t iter; if (bson_iter_init(&iter, bsonArray)) { while (bson_iter_next(&iter)) { // 直接追加迭代器指向的元素到数组构建器 bson_array_builder_append_iter(&bab, &iter); } } // 3. 追加目标对象到构建器 bson_array_builder_append_document(&bab, bsonObj); // 4. 生成最终的BSON数组 bson_t* finalArray = bson_array_builder_finish(&bab, NULL); // 验证结果(可选) char* jsonFinal = bson_as_json(finalArray, NULL); printf("最终数组JSON: %s\n", jsonFinal); bson_free(jsonFinal); // 5. 释放所有资源 bson_destroy(bsonObj); bson_destroy(bsonArray); bson_destroy(finalArray); return 0; }
关键说明
bson_array_builder_append_iter直接复用原数组的元素数据,无需重新序列化,性能接近直接内存复制,不存在“效率极低”的问题。- 禁止使用
bson_concat处理数组:该函数会将第二个文档的所有键值对合并到第一个文档,数组的数字键会发生冲突(比如两个数组的"0"键会覆盖),导致数组结构完全错误。 - 始终记得检查
bson_new_from_json的返回值,处理解析错误。
内容的提问来源于stack exchange,提问作者user2960174
相关产品推荐
相关产品推荐

