Protobuf-net 3:布尔属性反序列化后值异常求助
Protobuf-net 反序列化后布尔属性值被默认值覆盖的解决办法
问题原因
Protobuf的核心设计规则是默认值字段不会被序列化,而protobuf原生布尔类型的默认值是false。你的User类中IsSuperUser默认值设为true,当你将该属性赋值为false时,这个值等于protobuf的原生默认值,序列化时该字段不会被写入数据流。反序列化时,protobuf-net会自动用类定义的默认值true填充这个未被序列化的字段,导致属性值被覆盖。
解决方案
1. 用[DefaultValue]显式标记属性默认值
给IsSuperUser添加DefaultValueAttribute,明确告诉protobuf-net该属性的默认值是true。这样当属性值为false时(与标记的默认值不符),就会被正常序列化:
using System.ComponentModel; public class User { public string Name { get; set; } [DefaultValue(true)] public bool IsSuperUser { get; set; } = true; }
2. 标记字段为必填(不推荐)
通过[ProtoMember]的IsRequired参数强制序列化该字段,即使值等于默认值。但这种方式违背了protobuf“默认值不序列化”的设计初衷,会增加序列化后的 payload 体积:
using ProtoBuf; [ProtoContract] public class User { [ProtoMember(1)] public string Name { get; set; } [ProtoMember(2, IsRequired = true)] public bool IsSuperUser { get; set; } = true; }
3. 改用可空布尔类型
如果业务逻辑允许,将IsSuperUser改为bool?(可空布尔类型)。此时null是该类型的默认值,当你赋值为false时,值不等于默认值,会被正常序列化,反序列化后也能保留false:
public class User { public string Name { get; set; } public bool? IsSuperUser { get; set; } = true; }
验证修改
调整代码后重新执行序列化和反序列化操作,IsSuperUser属性将保持你设置的false值,不会被默认值覆盖。
内容的提问来源于stack exchange,提问作者Nizar Ahammad
相关产品推荐
相关产品推荐

