2

我運行,需要不同的編程語言(主要是JAVA,C++)之間有沒有一種方法可以在不知道其節儉類型的情況下將原始字節[]反序列化爲節儉對象?

  • 間通信的一個項目。
  • 可序列化/反序列化爲二進制格式和JSON格式。
  • IDL來產生不同的語言

節儉這些標準完全匹配類的代碼,雖然我們並不需要它的RPC功能。我們將通過MQ發送/接收序列化的節儉數據。序列化對象非常簡單。然而,當涉及到反序列化,我們不能做這樣的事情:

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; 
} 

看來,我們必須告訴節儉到底哪個結構需要反序列化到像:

byte[] data = recv(); 
TypeA a; 
TDeserializer.deserialize(a, data); 

只是想知道,如果有一種將原始數據反序列化爲節儉對象而不知道其確切類型的方法。

謝謝!

回答

11

節儉連載消息本身並不包含類型信息,所以解串器必須知道消息的數據類型。但是,可以將所有必要的數據類型合併到一起。

節儉代碼:

union Message { 
    1: TypeA a; 
    2: TypeB b; 
} 

反序列化代碼:

byte[] data = recv(); 
Message msg; 
TDeserializer.deserialize(msg, data); 
<find out message type with msg.getSetField()> 

如果您需要添加新的消息類型,只需添加一個字段到工會。如果你不碰老場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 
} 
+0

這是非常全面的答案。感謝你!這將解決我的擔憂。奇怪的是,聯盟沒有記錄在任何地方。 – zhou

+0

它是,但只在JIRA。 https://issues.apache.org/jira/browse/THRIFT-409 – JensG

+1

此方法適用於Golang嗎?我正在使用官方實現,無法在聯合結構上找到這個神奇的方法。我錯過了什麼? –