我正在运行一个需要
- 不同编程语言(主要是 java、c++)之间的相互通信。
- 可以序列化/反序列化为二进制格式和json格式。
- IDL 为不同语言生成类代码
Thrift 完全符合这些标准,尽管我们不需要它的 RPC 函数。我们将通过 MQ 发送/接收序列化的 thrift 数据。序列化对象非常简单。然而,当谈到反序列化时,我们不能这样做:
byte[] data = recv();
Object object = TDeserializer.deserialize(data);
if (object instanceof TypeA) {
TypeA a = (TypeA) object;
} else if (object instanceof TypeB) {
TypeB b = (TypeB) object;
}
看来我们必须准确地告诉 thrift 它需要反序列化成哪个结构:
byte[] data = recv();
TypeA a;
TDeserializer.deserialize(a, data);
只是想知道是否有一种方法可以在不知道其确切类型的情况下将原始数据反序列化为 thrift 对象。
谢谢!!
最佳答案
Thrift 序列化消息本身不包含类型信息,因此反序列化器必须知道消息数据类型。但是,可以将所有必要的数据类型包装到联合中。
节俭代码:
union Message {
1: TypeA a;
2: TypeB b;
}
反序列化代码:
byte[] data = recv();
Message msg;
TDeserializer.deserialize(msg, data);
<find out message type with msg.getSetField()>
如果需要添加新的消息类型,只需在union中添加一个字段即可。如果您不接触旧的字段 ID,您将保持向后兼容性:
union Message {
1: TypeA a;
2: TypeB b;
3: TypeC c; <-- OK
}
您将能够接收来自旧生产者的消息(他们永远不会发送TypeC
消息)并向旧生产者发送TypeA
/TypeB
消息消费者。如果您向不知道字段 #3 的消费者发送 TypeC
消息,它将得到异常。
这种方法的一大优点是类型信息非常紧凑。如果您使用TCompactProtocol
,在大多数情况下类型信息只会占用 1 个额外字节(如果 Message
中的字段 ID 小于 127)。
请注意,如果更改字段 ID,将失去向后兼容性。例如:
union Message {
1: TypeA a;
2: TypeC c; <-- Wrong
3: TypeB b; <-- Wrong
4: TypeD d; <-- OK
}
关于cross-platform - 有没有办法在不知道 thrift 类型的情况下将原始 byte[] 反序列化回 thrift 对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16917361/