由於thrift的型別沒有類似java的Object型別,當我們想用thrift來定義一個具體型別不確定的物件時候,會有不知如何定義的困擾。
方法一:使用聯合(union)
union的特點是結構中的每個field之間的關係是互斥的,即只能有一個field被使用被賦值。所以可以根據我們未知型別物件的類型範圍定義一個union
union JavaObjectArg { 1: i32 int_arg; 2: i64 long_arg; 3: string string_arg; 4: bool bool_arg; 5: binary binary_arg; 6: double double_arg;}struct OneResp { 1: list<JavaObjectArg> myList,}
union的使用方式
可以透過生成的JavaObjectArg.java中的standardSchemeReadValue方法獲取,對應的型別
protected Object standardSchemeReadValue(org.apache.thrift.protocol.TProtocol iprot, org.apache.thrift.protocol.TField field) throws org.apache.thrift.TException
或者,透過對應型別的get方法獲得結果。例如獲取*int*型別的結果
public int getInt_arg() { if (getSetField() == _Fields.INT_ARG) { return (Integer)getFieldValue(); } else { throw new RuntimeException("Cannot get field 'int_arg' because union is currently set to " + getFieldDesc(getSetField()).name); }}
方法二:使用特殊型別(binary)
binary:是未編碼的位元組序列
類似,當我們想定義一個List<Object>時
struct TwoResp { 1: list<binary> myList,}
生成後,會變成ByteBuffer型別,根據需要的型別對應進行轉換即可。
public List<ByteBuffer> myList;
終極方法:序列化
終極方案當然還是先把包含Object型別的物件或者集合,先序列化成一個jsonString。此時,在thrift中定義成string即可。使用時,由呼叫端將這個string物件根據約定的物件反序列化後即可獲得需要的型別。
以下面的介面為例,透過Jackson序列化。
service ITMuouThriftService { string testScene(string param);}
服務端序列化:
Map<String, Object> decisionMap = Maps.newHashMapWithExpectedSize(1); decisionMap.put("res": 1);return new ObjectMapper().writeValueAsString(decisionMap)
呼叫端反序列化:
TypeReference<Map<String, Object>> MAP_TYPE_REF = new TypeReference<Map<String, Object>>() { };String res = muouThriftService.testScene("test");Map<String, Object> resultMap = new ObjectMapper().readValue(res, MAP_TYPE_REF);
最新評論