开发者

null string deserialized to empty string when using protobuf-net

开发者 https://www.devze.com 2022-12-28 22:10 出处:网络
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 (\"\").

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>(开发者_Go百科stream, message);                
     stream.Close();
}

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


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 ?? "");}
    }
}
0

精彩评论

暂无评论...
验证码 换一张
取 消