Serialization of non-required fields in protobuf-net
- by David Hedlund
I have a working java client that is communicating with Google, through ProtoBuf serialized messages. I am currently trying to translate that client into C#.
I have a .proto file where the parameter appId is an optional string. Its default value in the C# representation as generated by the protobuf-net library is an empty string, just as it is in the java representation of the same file.
message AppsRequest {
optional AppType appType = 1;
optional string query = 2;
optional string categoryId = 3;
optional string appId = 4;
optional bool withExtendedInfo = 6;
}
I find that when I explicitly set appId to "" in the java client, the client stops working (403 Bad Request from Google). When I explicitly set appId to null in the java client, everything works, but only because hasAppId is being set to false (I'm uncertain as to how that affects the serialization).
In the C# client, I always get 403 responses. I don't see any logic behind the distinction between not setting a value, and setting the default value, that seems to make all the difference in the java client. Since the output is always a binary stream, I am not sure if the successful java messages are being serialized with an empty string, or not serialized at all.
In the C# client, I've tried setting IsRequired to true on the ProtoMember attribute, to force them to serialize, and I've tried setting the default value to null, and explicitly set "", so I'm quite sure I've tried some configuration where the value is being serialized. I've also played around with ProtoBuf.ProtoIgnore and at some point, removing the appId parameter altogether, but I haven't been able to avoid the 403 errors in C#.
I've tried manually copying the serialized string from java, and that resolved my issues, so I'm certain that the rest of the HTTP Request is working, and the error can be traced to the serialized object.
My serialization is simply this:
var clone = ProtoBuf.Serializer.DeepClone(request);
MemoryStream ms = new MemoryStream(2000);
ProtoBuf.Serializer.Serialize(ms, clone);
var bytearr = ms.ToArray();
string encodedData = Convert.ToBase64String(bytearr);
I'll admit to not being quite sure about what DeepClone does. I've tried both with and without it...