存储flatbuffers对象的非根表,以供以后反序列化

时间:2018-08-20 23:23:30

标签: flatbuffers

考虑以下平面缓冲区架构(来自this stack overflow question):

table Foo {
    ...
}
table Bar {
    value:[Foo];
}
root_type Bar;

假设一个典型对象中Foo的数量很大,因此我们要避免修改架构以使Foo成为root_type

场景:

C ++客户端序列化一个适当的flatbuffers对象,并将其发布到另一个组件(nodejs后端),该组件将部分反序列化该对象并将代表每个Foo的二进制文件存储在数据库中作为单独的文档:

const buf = new flatbuffers.ByteBuffer(req.body)
const bar = fbs.Bar.getRootAsBar(buf)
for (let i = 0; i < bar.valueLength(); i++) {
  const foo = bar.value(i)
  let item = {
    'raw': foo.bb.bytes_ // <-- primary suspect
  }
  // ... store `item` as an individual entity (mongodb doc)
}

稍后,第三个组件获取存储在mongodb文档的“原始”键中的二进制数据,并尝试将其反序列化为Foo对象:

auto mongoCol = db.collection("results");
auto mongoResult = mongoCol.find_one(
    bsoncxx::builder::stream::document{}
    << "_id" << oid << bsoncxx::builder::stream::finalize);
// ...check that mongoResult is not null
const auto result = mongoResult->view();
const auto& binary = result["raw"].get_binary();
std::string content((const char*)binary.bytes, binary.size);
const auto& foo = flatbuffers::GetRoot<fbs::Foo>(content.c_str());

问题:

但是给定为foo的指针没有指向预期的数据,对foo的任何操作都可能导致段错误或访问冲突。

怀疑:

我推测根本原因是存储在数据库中的二进制文件根据原始消息使用了偏移量。因此,它在其自己的原始格式中实质上是无效的,并且偏移量应在插入数据库之前进行重新调整。但是我看不到任何Flatbuffers函数API来重新调整偏移量吗?

不太可能的根本原因可能是最终的反序列化代码不完整,我们必须重新调整偏移量?

我怀疑它与偏移量有关的原因是,如果我们做出折衷并在每个Bar向量中使用一个Foo元素发布较小的flatbuffers对象(并更改后端代码以存储{{1 }}改为bar.bb.bytes

问题:

以任何方式,甚至有可能获取您知道代表所需表的更大的正确构造的flatbuffers二进制文件的一部分,并对其进行反序列化吗?

1 个答案:

答案 0 :(得分:1)

您不能简单地从更大的FlatBuffer中逐字节复制子表,因为此数据不一定是连续的。最好的解决方法是改为让Bar[FooBuffer]的地方存储table FooBuffer { buf:[byte] (nested_flatbuffer: Foo) }。当您构造其中一个时,您将每个Foo构造成自己的FlatBufferBuilder,然后将结果字节存储在父级中。然后,当您需要分别存储Foo时,这将成为简单的副本。