2015-09-16 14 views
7

मैं जानना चाहता हूं कि प्रोटोबफ को बदलने के लिए कोई भी मूल प्रोटोबफ संदेश प्रकार और इसके विपरीत टाइप करें। जावा में किसी भी के लिए संदेश से आसान है:प्रोटोबफ 3.0 किसी भी प्रकार का पैक/अनपैक

Any.Builder anyBuilder = Any.newBuilder().mergeFrom(protoMess.build()); 

लेकिन मैं कैसे पार्स कर सकते हैं कि किसी भी वापस originial संदेश को (जैसे, "protoMess" के प्रकार के लिए)? मैं शायद इसे वापस पढ़ने के लिए स्ट्रीम पर सबकुछ पार्स कर सकता हूं, लेकिन यह वही नहीं है जो मैं चाहता हूं। मैं इस तरह कुछ परिवर्तन करना चाहता हूं:

ProtoMess.MessData.Builder protoMessBuilder = (ProtoMess.MessData.Builder) transformToMessageBuilder(anyBuilder) 

मैं इसे कैसे प्राप्त कर सकता हूं? क्या यह जावा के लिए पहले ही लागू है? Protobuf Language Guide का कहना है कि पैक और अनपैक विधियां थीं, लेकिन जावा में कोई भी नहीं है। अग्रिम में धन्यवाद :)

उत्तर

5

उत्तर थोड़ा देर हो सकता है लेकिन शायद यह किसी को भी मदद करता है।

प्रोटोकॉल बफर 3 pack और unpack के वर्तमान संस्करण में available in Java हैं।

अपने उदाहरण पैकिंग में की तरह किया जा सकता है:

Any anyMessage = Any.pack(protoMess.build())); 

और की तरह खोल:

ProtoMess protoMess = anyMessage.unpack(ProtoMess.class); 

यहाँ भी नेस्टेड Any संदेश के साथ प्रोटोकॉल बफ़र संदेशों को संभालने के लिए एक पूर्ण उदाहरण है:

प्रोटोकॉलबफर फ़ाइलें

एक साधारण प्रोटोकॉल बफ़र एक नेस्टेड Any संदेश के साथ फाइल दिखाई देगा:

syntax = "proto3"; 

import "google/protobuf/any.proto"; 

message ParentMessage { 
    string text = 1; 
    google.protobuf.Any childMessage = 2; 
} 

एक संभावित नेस्टेड संदेश तो हो सकता है:

syntax = "proto3"; 

message ChildMessage { 
    string text = 1; 
} 

पैकिंग

पूर्ण संदेश निर्माण करने के लिए निम्नलिखित फ़ंक्शन का उपयोग किया जा सकता है:

public ParentMessage createMessage() { 
    // Create child message 
    ChildMessage.Builder childMessageBuilder = ChildMessage.newBuilder(); 
    childMessageBuilder.setText("Child Text"); 
    // Create parent message 
    ParentMessage.Builder parentMessageBuilder = ParentMessage.newBuilder(); 
    parentMessageBuilder.setText("Parent Text"); 
    parentMessageBuilder.setChildMessage(Any.pack(childMessageBuilder.build())); 
    // Return message 
    return parentMessageBuilder.build(); 
} 

अनपैक किया माता-पिता संदेश निम्न समारोह इस्तेमाल किया जा सकता से बच्चे संदेश पढ़ने के लिए:

public ChildMessage readChildMessage(ParentMessage parentMessage) { 
    try { 
     return parentMessage.getChildMessage().unpack(ChildMessage.class); 
    } catch (InvalidProtocolBufferException e) { 
     e.printStackTrace(); 
     return null; 
    } 
} 

संपादित करें:

अपने पैक संदेशों विभिन्न प्रकार कर सकते हैं, आप कर सकते हैं typeUrl पढ़ें और संदेश को अनपैक करने के लिए प्रतिबिंब का उपयोग करें।मान लें कि आप बच्चे संदेशों ChildMessage1 है और ChildMessage2 आप निम्न कर सकते हैं:

@SuppressWarnings("unchecked") 
public Message readChildMessage(ParentMessage parentMessage) { 
    try { 
     Any childMessage = parentMessage.getChildMessage(); 
     String clazzName = childMessage.getTypeUrl().split("/")[1]; 
     String clazzPackage = String.format("package.%s", clazzName); 
     Class<Message> clazz = (Class<Message>) Class.forName(clazzPackage); 
     return childMessage.unpack(clazz); 
    } catch (ClassNotFoundException | InvalidProtocolBufferException e) { 
     e.printStackTrace(); 
     return null; 
    } 
} 

आगे की प्रक्रिया के लिए, यदि आप instanceof साथ संदेश की प्रकृति है, जो बहुत ही कुशल नहीं है निर्धारित कर सकते हैं। आप एक निश्चित प्रकार के संदेश प्राप्त करना चाहते हैं, तो आप typeUrl सीधे तुलना करनी चाहिए:

public ChildMessage1 readChildMessage(ParentMessage parentMessage) { 
    try { 
     Any childMessage = parentMessage.getChildMessage(); 
     String clazzName = childMessage.getTypeUrl().split("/")[1]; 
     if (clazzName.equals("ChildMessage1")) { 
      return childMessage.unpack("ChildMessage1.class"); 
     } 
     return null 
    } catch (InvalidProtocolBufferException e) { 
     e.printStackTrace(); 
     return null; 
    } 
} 
+1

इस 'readChildMessage' के अलावा कोई अन्य रास्ता नहीं है? क्या होगा यदि मेरे पास दर्जनों अलग-अलग संदेश हैं जो आ सकते हैं? बस नए 'कोशिश-पकड़' ब्लॉक में जोड़ें? यहां तक ​​कि 'स्विच-केस' और पसंद बिल्कुल अस्वीकार्य है। – Sorona

+0

अच्छा सवाल, मैं यह जोड़ना भूल गया कि आप पैक किए गए संदेश का नाम 'typeURL' के रूप में प्राप्त कर सकते हैं। यह प्रतिबिंब के माध्यम से किसी संदेश को अनपैक करने की अनुमति देता है या सीधे यह तय करता है कि संदेश के साथ क्या करना है। मैंने अपने जवाब में दो उदाहरण जोड़े, मुझे आशा है कि इससे मदद मिलती है। – sundance

+0

बढ़िया! यह मेरी मदद की! – FisherCoder

संबंधित मुद्दे