Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

protobuf required field and default value

I am new to protobuf and I have started considering the following trivial example

message Entry {
  required int32 id = 1;
}

used by the c++ code

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

Even if the "id" field is required, since it has not been set, the size of the serialization buffer is 0 (??).

When I deserialize the message an error occurs:

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

Is it a normal behavior?

Francesco

ps- If I initialize "id" with the value 0, the behavior is different

pps- The SerializeToString function returns true, the ParseFromString returns false

like image 575
fbasile Avatar asked Mar 12 '13 11:03

fbasile


1 Answers

I dont think I exactly understand your question, but I'll have a go at the answer anyways. Hope this helps you in some way or the other :)

Yes this is normal behavior. You should add required only if the field is important to the message. It makes sense semantically. (why would you skip a required field). To enforce this, protobuf would not parse the message.

It sees that the field marked with number 1 is required, and the has_id() method is returning false. So it wont parse the message at all.

In the developer guide it is advised not to use required fields.

Required Is Forever You should be very careful about marking fields as required. If at some point you wish to stop writing or sending a required field, it will be problematic to change the field to an optional field – old readers will consider messages without this field to be incomplete and may reject or drop them unintentionally. You should consider writing application-specific custom validation routines for your buffers instead. Some engineers at Google have come to the conclusion that using required does more harm than good; they prefer to use only optional and repeated. However, this view is not universal.

Also

Any new fields that you add should be optional or repeated. This means that any messages serialized by code using your "old" message format can be parsed by your new generated code, as they won't be missing any required elements. You should set up sensible default values for these elements so that new code can properly interact with messages generated by old code. Similarly, messages created by your new code can be parsed by your old code: old binaries simply ignore the new field when parsing. However, the unknown fields are not discarded, and if the message is later serialized, the unknown fields are serialized along with it – so if the message is passed on to new code, the new fields are still available. Note that preservation of unknown fields is currently not available for Python

like image 80
Tushar Koul Avatar answered Oct 29 '22 18:10

Tushar Koul