首页 > 解决方案 > Flatbuffers:如何允许单个字段使用多种类型

问题描述

我正在为可以是多个值的参数列表编写通信协议模式:uint64、float64、string 或 bool。

如何将表字段设置为多个原始标量和非标量原始类型的联合?

我已经尝试过使用这些类型的联合,但在构建时出现以下错误:

$ schemas/foobar.fbs:28: 0: error: type referenced but not defined
  (check namespace): uint64, originally at: schemas/request.fbs:5

这是当前状态的架构:

namespace Foobar;

enum RequestCode : uint16 { Noop, Get, Set, BulkGet, BulkSet }

union ParameterValue { uint64, float64, bool, string }

table Parameter {
  name:string;
  value:ParameterValue;
  unit:string;
}

table Request {
  code:RequestCode = Noop;
  payload:[Parameter];
}

table Result {
  request:Request;
  success:bool = true;
  payload:[Parameter];
}

我正在寻找的最终结果是包含参数列表的请求和结果表,其中参数包含名称和值,以及可选的单位。

提前谢谢!

回答后解决方案: 这是我最后想出的,感谢 Aardappel。

namespace foobar;

enum RequestCode : uint16 { Noop, Get, Set, BulkGet, BulkSet }

union ValueType { UnsignedInteger, SignedInteger, RealNumber, Boolean, Text }

table UnsignedInteger {
  value:uint64 = 0;
}

table SignedInteger {
  value:int64 = 0;
}

table RealNumber {
  value:float64 = 0.0;
}

table Boolean {
  value:bool = false;
}

table Text {
  value:string (required);
}

table Parameter {
  name:string (required);
  valueType:ValueType;
  unit:string;
}

table Request {
  code:RequestCode = Noop;
  payload:[Parameter];
}

table Result {
  request:Request (required);
  success:bool = true;
  payload:[Parameter];
}

标签: schemaflatbuffers

解决方案


您目前不能将标量直接放在联合中,因此您必须将它们包装在表或结构中,其中 struct 可能是最有效的,例如

struct UInt64 { u:uint64 }
union ParameterValue { UInt64, Float64, Bool, string }

这是因为联合必须一致地具有相同的大小,因此它只允许您可以拥有偏移量的类型。

不过,一般来说,FlatBuffers 是一个强类型系统,您在此处创建的模式通过模拟动态类型的数据来撤销它,因为您的数据本质上是(字符串,任何类型)对的列表。使用专为该特定用例设计的系统可能会更好,例如 FlexBuffers(https://google.github.io/flatbuffers/flexbuffers.html,目前只有 C++),它明确具有全为字符串的映射类型 - > 任何类型对。

当然,更好的是不要如此通用地存储数据,而是为您拥有的每种类型的请求和响应创建一个新模式,并将参数名称放入字段中,而不是序列化数据。这是迄今为止最有效且类型安全的。


推荐阅读