为什么带有 protobuf 的 redis 将空数组保存为 null?
Why redis with protobuf is saving empty arrays as null?
我正在使用 protobuf-net 2.3.3 在 redis 服务器 2.8.2103 使用 StackExchange.Redis 1.2.6.
对于像这样的对象:
[ProtoContract(ImplicitFields = ImplicitFields.AllFields)]
public class Cachable { Foo[] Foos { get; set; } }
当我使用简单的方式保存时:
using (var memoryStream = new MemoryStream())
{
Serializer.Serialize(memoryStream, cachable);
database.HashSetAsync("category", "key", memoryStream.ToArray());
}
然后检索:
var response = database.HashGet("category", "key");
if (!response.HasValue) return null;
using (var memoryStream = new MemoryStream(response, false))
{
return Serializer.Deserialize<Cachable>(memoryStream);
}
如果缓存数组 Foos
有一个空实例,如 new Foo[0]
,一旦 Cachable
被反序列化,数组变为 null
。
这正在改变应用程序某些部分的行为并产生错误。
这种行为是预期的吗?有什么办法可以改变吗?
真正的问题是 Foo[0]
是 null
吗?如果是:
- protobuf 没有
null
的概念;它不能表示和存储 null,因此默认情况下 protobuf-net skips null 值,使这个 essentially 成为一个空数组
- 稍微注意 "empty packed primitives",protobuf 没有 "empty" 序列的概念;在 .proto 术语中,你谈论的是一个
repeated
字段,它有零个元素,这意味着:它根本不存在于有效负载中 根本
- 如果有效载荷中不存在它,它永远不会反序列化任何东西——因为有效载荷中从来没有任何东西可以告诉它 反序列化
所以:
- 避免
null
除非你的意思是一个可选的子元素;绝对避免在列表/数组/等中使用 null
- 不要假设空 lists/arrays/etc 将被库初始化为非空值
IMO,对于第二点,以下内容是合理和务实的:
Foo[] Foos { get; set; } = Array.Empty<Foo>();
(避免了初始化为 null
的问题)
我正在使用 protobuf-net 2.3.3 在 redis 服务器 2.8.2103 使用 StackExchange.Redis 1.2.6.
对于像这样的对象:
[ProtoContract(ImplicitFields = ImplicitFields.AllFields)]
public class Cachable { Foo[] Foos { get; set; } }
当我使用简单的方式保存时:
using (var memoryStream = new MemoryStream())
{
Serializer.Serialize(memoryStream, cachable);
database.HashSetAsync("category", "key", memoryStream.ToArray());
}
然后检索:
var response = database.HashGet("category", "key");
if (!response.HasValue) return null;
using (var memoryStream = new MemoryStream(response, false))
{
return Serializer.Deserialize<Cachable>(memoryStream);
}
如果缓存数组 Foos
有一个空实例,如 new Foo[0]
,一旦 Cachable
被反序列化,数组变为 null
。
这正在改变应用程序某些部分的行为并产生错误。
这种行为是预期的吗?有什么办法可以改变吗?
真正的问题是 Foo[0]
是 null
吗?如果是:
- protobuf 没有
null
的概念;它不能表示和存储 null,因此默认情况下 protobuf-net skips null 值,使这个 essentially 成为一个空数组 - 稍微注意 "empty packed primitives",protobuf 没有 "empty" 序列的概念;在 .proto 术语中,你谈论的是一个
repeated
字段,它有零个元素,这意味着:它根本不存在于有效负载中 根本 - 如果有效载荷中不存在它,它永远不会反序列化任何东西——因为有效载荷中从来没有任何东西可以告诉它 反序列化
所以:
- 避免
null
除非你的意思是一个可选的子元素;绝对避免在列表/数组/等中使用null
- 不要假设空 lists/arrays/etc 将被库初始化为非空值
IMO,对于第二点,以下内容是合理和务实的:
Foo[] Foos { get; set; } = Array.Empty<Foo>();
(避免了初始化为 null
的问题)