protobuf-net:包含null元素的列表

时间:2017-03-23 02:43:39

标签: list serialization null deserialization protobuf-net

public MyType {

  [ProtoMember(1)]
  public int Index;

  [ProtoMember(2)]
  public string Name;

  public MyType() {
  }

  public MyType(int index, string name) {
    Index = index;
    Name = name;
  }
}

var element0 = new MyType(0,"element index 0");
var element1 = null;
var element2 = new MyType(2,"element index 2");
var list = new List<MyType> {element0, element1, element2}

由于元素索引1为空,protobuf-net序列化器将从序列化字节中省略该元素。

在电线的另一边,发生了一些非常有趣的事情:

protobuf-net反序列化器读取字节,得知3个元素是预期的,但只查找元素索引0和2的字节。因此它将元素索引1创建为MyType的空实例。

因此反序列化列表相当于:

var element0 = new MyType(0,"element index 0");   
var element1 = new MyType(0,null); 
var element2 = new MyType(2,"element index 2");
var list = new List<MyType> {element0, element1, element2}

但这不是预期的。 Null与空对象不同,并且具有重复Index = 0和Name = null的元素的存在可能对处理代码产生严重的不利后果 - 理所当然地不应该知道或不关心serdes细节。 / p>

有解决方法吗?

1 个答案:

答案 0 :(得分:1)

基本上,不,没有解决方法,并且它不是protobuf-net支持的方案。底层协议缓冲区格式(protobuf-net实现)没有null的概念;我无法在常规格式中表示null实例。类列表只是一个重复长度前缀的节点块,所以(以密集的二进制格式,而不是文本):

[field 1, length-prefixed] [length prefix] [payload for element index 0]
[field 1, length-prefixed] [length prefix] [payload for element index 1]
[field 1, length-prefixed] [length prefix] [payload for element index 2]
... etc

我对列表中的空值只有两个选项:

  • 忽略他们
  • 将它们视为零长度

Protobuf-net目前使用第二种方法,但是:零长度类基本上是new MyType();零长度完全有效,并且在协议缓冲区中定义良好。

与其他一些格式不同,我无法在任何地方添加额外的元数据来表示&#34;我是一个空的&#34; (例如,xml中的@xsi:nil)。

代码,但我已经检查过,目前还没有对空值的支持 - 我接受这是一个疏忽,但我还要强调,#&#34;保留引用&#34;代码不是标准的protobuf ,任何其他库(java,golang等)都可能难以使用该配置;如果你知道你只是将protobuf-net与protobuf-net谈论,那么我只会提倡。当然,null支持目前还不存在,并且需要黑客攻击:)