2013-03-12 328 views
5

我是新來的protobuf和我已經開始考慮下面簡單的例子protobuf的必填字段和默認值

message Entry { 
    required int32 id = 1; 
} 

由C++代碼中使用

#include <iostream> 
#include "example.pb.h" 
int main() { 
    std::string mySerialized; 
    { 
    Entry myEntry; 
    std::cout << "Serialization succesfull " 
       << myEntry.SerializeToString(&mySerialized) << std::endl; 
    std::cout << mySerialized.size() << std::endl; 
    } 
    Entry myEntry; 
    std::cout << "Deserialization successfull " 
      << myEntry.ParseFromString(mySerialized) << std::endl; 
} 

即使「ID」字段因爲尚未設置,所以序列化緩衝區的大小爲0(??)。

當我反序列化消息時發生錯誤:

[libprotobuf ERROR google/protobuf/message_lite.cc:123] Can't parse message of type "Entry" because it is missing required fields: id 

它是一個正常的行爲?

弗朗西斯

PS-如果我初始化 「ID」 值爲0,該行爲是不同的

PPS-的SerializeToString函數返回true,則ParseFromString返回false

+0

請不要這些方法有返回值來告訴您它是否有效嗎?你在檢查他們嗎? – 2013-03-12 11:22:08

+0

請注意,零長度緩衝區在protobuf中是完全有效的 - 如果沒有要序列化的字段 – 2013-03-12 12:07:51

回答

4

我不認爲我完全理解你的問題,但無論如何我都會接受答案。希望這可以幫助你以某種方式或其他:)

是的這是正常的行爲。只有在該字段對消息很重要時,您才應添加required。它在語義上很有意義。 (爲什麼你會跳過一個必填字段)。爲了執行此操作,protobuf不會分析消息。

它看到標有數字1的字段是必需的,並且has_id()方法返回false。所以它不會解析信息。

developer guide建議不要使用必填字段。

必填永遠您應該非常小心地根據需要標記字段。如果您希望在某個時候停止撰寫或發送必填字段,將字段更改爲可選字段會有問題 - 舊讀者會認爲沒有此字段的郵件不完整,可能會無意中拒絕或放棄郵件。您應該考慮爲您的緩衝區編寫特定於應用程序的自定義驗證例程。 Google的一些工程師已經得出結論:使用所需要的不僅僅是好處而已,他們更喜歡只使用可選的和重複的。但是,這種觀點並不普遍。

而且

您添加應選配或重複任何新的領域。這意味着任何由代碼使用「舊」消息格式進行序列化的消息都可以通過新生成的代碼進行分析,因爲它們不會丟失任何必需的元素。您應該爲這些元素設置合理的默認值,以便新代碼可以正確地與舊代碼生成的消息進行交互。同樣,由新代碼創建的消息可以由舊代碼解析:舊的二進制文件在解析時會簡單地忽略新字段。但是,未知字段不會被丟棄,並且如果稍後序列化消息,則未知字段將與其一起序列化 - 因此,如果消息傳遞給新代碼,新字段仍然可用。請注意,保留未知字段目前不適用於Python