如何序列化数组中的空值?
Posted
技术标签:
【中文标题】如何序列化数组中的空值?【英文标题】:How to serialize null values in array? 【发布时间】:2021-12-18 13:51:12 【问题描述】:我在 Windows 平台上使用 protobuf-net v3.0.101 并在使用 grpc protobuf-net 对其进行序列化时获取以下字符串数组中的空值异常:
我已经这样定义了我的 DataContract:
[DataContract]
public class StringArray
[DataMember(Order = 1)]
public string[] StrArray;
这是我尝试序列化的实际消息:
var stringArray = new StringArray() StrArray = new string[] "1", "2", null, "3" ;
而且,这就是我调用 Serializer 的方式:
method.RequestMarshaller.ContextualSerializer(request, transmitPayload);
这是一个例外:
FAIL: Error: Unhandled exception in required test method. An element of type System.String was null; this might be as contents in a list/array. (System.NullReferenceException: An element of type System.String was null; this might be as contents in a list/array
at ProtoBuf.Internal.ThrowHelper.ThrowNullRepeatedContents[T]()
at ProtoBuf.Serializers.RepeatedSerializer`2.Write[TEnumerator](State& state, Int32 fieldNumber, SerializerFeatures category, WireType wireType, TEnumerator& values, ISerializer`1 serializer)
at ProtoBuf.Serializers.VectorSerializer`1.Write(State& state, Int32 fieldNumber, SerializerFeatures category, WireType wireType, T[] values, ISerializer`1 serializer)
at ProtoBuf.Serializers.RepeatedSerializer`2.WriteRepeated(State& state, Int32 fieldNumber, SerializerFeatures features, TCollection values, ISerializer`1 serializer)
at proto_29(State& , StringArray )
at ProtoBuf.ProtoWriter.State.SerializeRoot[T](T value, ISerializer`1 serializer)
at ProtoBuf.MeasureState`1..ctor(TypeModel model, T& value, Object userState, Int64 abortAfter)
at ProtoBuf.Meta.TypeModel.Measure[T](T value, Object userState, Int64 abortAfter)
at ProtoBuf.Meta.TypeModel.ProtoBuf.IMeasuredProtoOutput<System.Buffers.IBufferWriter<System.Byte>>.Measure[T](T value, Object userState)
at ProtoBuf.Grpc.Configuration.ProtoBufMarshallerFactory.ContextualSerialize[T](T value, SerializationContext context)
【问题讨论】:
呃.. 异常说“你的字符串数组中有一个空值”,而你的字符串数组的第三个位置有一个空值 【参考方案1】:这里的问题是:底层的protobuf格式没有null的概念。我根本无法以明显的方式将其编码到数组中。
在 V2 中,我们做了一些事情,将所有数组元素(启用此功能)包装在一个额外的层中,以允许我们解释空值,但这会占用更多的网络空间,不是就地静默替换,并且解释起来并不明显。我还没有在 V3 中重新添加它,但是如果非常需要它,我们可以这样做。但是,今天这样做的一种懒惰方法是序列化 Foo[]
其中 Foo
是一个类型,具有 string
作为唯一成员,字段 1。它可能是一个值-类型 - 甚至可能是带有单个字段的 readonly struct record
。
【讨论】:
1) 哪个解决方案的性能更高,将其序列化为Foo[]
或 V3 的“某事”解决方案? 2) 如果固定在 V3 上会很高效,那么需要付出多少努力?什么时候可以发布? 3) 任何实现细节如何为 V2 完成,将帮助我理解它的复杂性。谢谢。
@Priyanshu 线上的字节是相同的;它将节省的是调用方的额外代码和分配(即您的代码)。空跟踪的实现增量基本上是一些额外的代码来欺骗额外的层 - 可能不是很大,可能需要半天到一天的努力;已经考虑了边缘情况(感谢 V2),所以没有很多悬而未决的问题 - 只是:找时间去做(最终,如果我的个人家庭时间等)
我已经通过定义readonly struct record
解决了这个问题,就像你提到的那样。但是这个解决方案没有太大的可扩展性,我们有很多包含数组的 dto 或另一个再次包含数组的对象。另一个问题是,我无法区分接收端的空数组或空数组,两者都被反序列化为空。 IEnumerable以上是关于如何序列化数组中的空值?的主要内容,如果未能解决你的问题,请参考以下文章