Search code examples
c#serializationdeserializationprotobuf-net

ProtoBuf-Net error message " Invalid field in source data: 0"


I succeed in serializing instances of the following class but when I try to deserialize right after I get the following error message: " Invalid field in source data: 0".

I have no clue what it refers to because I find below class straight forward. I just updated protobuf-net version to 2.00.614 (runtime version: 2.0.50727).

Any idea whether I am possibly overlooking something trivial?

[ProtoContract]
public class TimeSeriesProperties 
{
    [ProtoMember(1)]
    public string TimeSeriesName { get; private set; }
    [ProtoMember(2)]
    public string FileName { get; private set; }
    [ProtoMember(3)]
    public string TemplateName { get; private set; }
    [ProtoMember(4)]
    public int PacketLength { get; private set; }
    [ProtoMember(5)]
    public long FileSizeBytes { get; set; }
    [ProtoMember(6)]
    public long NumberRecords { get; set; }
    [ProtoMember(7)]
    public DateTime DateTimeStart { get; set; }
    [ProtoMember(8)]
    public DateTime DateTimeEnd { get; set; }

    public TimeSeriesProperties()
    {

    }

    public TimeSeriesProperties(string timeSeriesName, string fileName, string templateName, int PacketLength)
    {
        this.TimeSeriesName = timeSeriesName;
        this.FileName = fileName;
        this.TemplateName = templateName;
        this.PacketLength = PacketLength;
    }

}

public static byte[] Serialize_ProtoBuf<T>(T serializeThis)
    {
        using (var stream = new MemoryStream())
        {
            ProtoBuf.Serializer.Serialize<T>(stream, serializeThis);
            return stream.GetBuffer();
        }
    }

    public static T Deserialize_ProtoBuf<T>(byte[] byteArray)
    {
        using (var stream = new MemoryStream(byteArray))
        {
            return ProtoBuf.Serializer.Deserialize<T>(stream);
        }
    }

Solution

  • The most common cause I've seen of this is simply incorrect use of GetBuffer() on a MemoryStream. That was already my hunch when I added my comment, but you've confirmed it:

    using (var stream = new MemoryStream())
    {
        ProtoBuf.Serializer.Serialize<T>(stream, serializeThis);
        return stream.GetBuffer();
    }
    

    GetBuffer returns the oversized backing-buffer. It has garbage at the end of it. It is perfectly fine to use GetBuffer, as long as you also record the .Length, which is the amount of valid data in there. This can avoid an extra allocation of a potentially large array. But in your case, a simpler approach is probably to use ToArray() to get a right-sized buffer:

    using (var stream = new MemoryStream())
    {
        ProtoBuf.Serializer.Serialize<T>(stream, serializeThis);
        return stream.ToArray();
    }