tags:

views:

127

answers:

1

I am using protobuf-net to serialize and deserialize my messages. My message also contain come strings that can be null. However when I deserialize them on the other side, I get empty strings ("").

According to google docs, the default value for string type in empty string. What could be the resolution for this issue?

Here is the code I am using:

Command message = new Command();
message.s_value = null;
using (MemoryStream stream = new MemoryStream())
{
     Serializer.Serialize<Command>(stream, message);                
     stream.Close();
}

Upon deserializing the same stream, I get s_value = ""

+2  A: 

I would guess that your type is explicitly setting the string to "" in the parameterless constructor. Could you check?

The way that protobuf-net handles this is:

  • for a null, nothing is sent (the protobuf wire-format has no way of explicitly expressing a null, but we can treat it as optional and omit it)
  • for a "", a 0-length pattern is sent, which should be deserialized as ""
  • for a non-empty string, the length and the string is sent, and is deserialized

During deserialization, in the null case it simply leaves your field/property alone, since it has no data to process. If the type sets the default to "" it will stay as "".

Note that in "v2" (I expect to release this in the next two weeks), you can optionally tell it to use the WCF approach of "don't run any constructor", which will have the effect of leaving it as null even if the default constructor assigns it.

There are also some tricks you can do (with "v1") to send a bool flag (as a separate property) to mean null; let me know if you want an example of this.


Edit: here's an example of a "v1" trick to get around this; the "v2" approach of "ignore the constructor" is probably a better option long-term, though:

[DataContract]
class Test {
    public Test() { Value = ""; } // a constructor that assigns the value

    [DataMember(Order = 1)]
    public string Value { get; set; } // our standard data
    [DataMember(Order = 2)]
    private bool ValueIsNull { // only exists to indicate explicit null
        get { return Value == null; }
        set { Value = value ? null : (Value ?? "");}
    }
}
Marc Gravell
I have updated the question and included the sample code I am testing. I have checked the code, and the string type field is always initialized with an empty string upon declaration. I did figured out some work arounds (like the one you mentioned in eg) but I was thinking of accomplishing without including more information or changing the generated code.
cornerback84
@cornerback84 - is this code generated from .proto? Or your own generator?
Marc Gravell
The code is generated from .proto. I using protobuf-net compiler to generate it (the new vs2008 integration).
cornerback84
@cornerback84 - OK, I *expect* that the "detect missing" optional flag will resolve this. At the command-line, `-p:detectMissing`. In the IDE you need to tweak the custom tool /namespace/ field - I seem to recall by adding ";detectMissing" (or "detectMissing" if it is blank).
Marc Gravell
I used the flag, but its still producing the same outcome. I'll check it further.
cornerback84