пустая строка десериализуется в пустую строку при использовании protobuf-net - PullRequest
2 голосов
/ 30 апреля 2010

Я использую protobuf-net для сериализации и десериализации моих сообщений. Мое сообщение также содержит строки, которые могут быть нулевыми. Однако, когда я десериализую их на другой стороне, я получаю пустые строки ("").

Согласно Google Docs, значение по умолчанию для типа строки в пустой строке. Каким может быть решение этой проблемы?

Вот код, который я использую:

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

После десериализации того же потока я получаю s_value = ""

1 Ответ

4 голосов
/ 30 апреля 2010

Я бы предположил , что ваш тип явно устанавливает строку в "" в конструкторе без параметров. Не могли бы вы проверить?

Способ, которым протокол protobuf-net обрабатывает это:

  • для null, ничего не отправляется (у протокола-протокола protobuf нет способа явно выразить null, но мы можем трактовать его как необязательный и опустить его)
  • для "" отправляется шаблон длины 0, который должен быть десериализован как ""
  • для непустой строки, длина и строка отправляются и десериализуются

Во время десериализации, в случае null он просто оставляет ваше поле / свойство в покое, поскольку у него нет данных для обработки. Если тип устанавливает значение по умолчанию "", оно останется как "".

Обратите внимание, что в "v2" (я ожидаю выпустить его в течение следующих двух недель), вы можете при желании сказать ему использовать подход WCF "не запускать конструктор", что приведет к его выходу как null , даже если конструктор по умолчанию назначает его.

Есть также некоторые приемы, которые вы можете сделать (с помощью «v1»), чтобы отправить флаг bool (как отдельное свойство), означающий null; дайте мне знать, если вы хотите пример этого.


Edit: вот пример трюка "v1", чтобы обойти это; "v2" подход "игнорировать конструктор", вероятно, является лучшим вариантом в долгосрочной перспективе, хотя:

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