在protobuf.net中,在新的内存流上出现了无效的线类型错误

本文关键字:无效 错误 类型 net protobuf 内存 | 更新日期: 2023-09-27 18:17:03

我正在尝试解析从外部服务收到的protobuf消息。我知道这个数据是一个有效的protobuf消息,并且我知道在将它发送给反序列化器之前,我不会意外地弄乱它。下面是我的代码:

public static T DeserializeFromBytes<T>(byte[] encoded)
{
    MemoryStream stream = new MemoryStream(encoded);
    stream.SetLength(encoded.Length);
    stream.Capacity = encoded.Length;
    T decoded = (T)Serializer.Deserialize<T>(stream);
    stream.Close();
    return decoded;
}

我像这样调用这个方法:

MercuryReply header = ProtobufUtils.DeserializeFromBytes<MercuryReply>(Convert.FromBase64String(metadata[0]));

metadata[0]是一个base64字符串,包含一个protobuf消息。一个示例看起来像这样:

CjRobTovL21ldGFkYXRhL2FsYnVtL2M1MzU3MTA0M2U4ODQ3YjRhODc1YzVlNmZiNmNiZTdmEhp2bmQuc3BvdGlmeS9tZXRhZGF0YS1hbGJ1bSCQAzIYCgpNRC1WZXJzaW9uEgoxMzcwMzc5NTA1Mg8KBk1DLVRUTBIFNjk2MDQyGQoPTUMtQ2FjaGUtUG9saWN5EgZwdWJsaWMyDwoHTUMtRVRhZxIELD8q + Q = =

现在,当我运行程序时,我在反序列化时得到一个Invalid wire-type错误。我看不出有什么理由会发生这种事。有什么明显的我没注意到吗?

在protobuf.net中,在新的内存流上出现了无效的线类型错误

这通常意味着:

  • 二进制文件是无效的(人们总是把二进制文件弄得一团糟;使用base-64是完全可以的,但是,如果它需要作为字符串存储/传输)
  • 数据中存在不匹配(例如,字段2在数据中是varint,但在类型中是string)

根据你的二进制,我拼凑了MercuryReply可能看起来像:

[ProtoContract]
public class MercuryReply
{
    [ProtoMember(1)]
    public string Location { get; set; }
    [ProtoMember(2)]
    public string ContentType { get; set; }
    [ProtoMember(4)]
    public int ResponseStatus { get; set; }
    [ProtoMember(6)]
    public Dictionary<string, string> Headers { get { return headers; } }
    private readonly Dictionary<string, string> headers
        = new Dictionary<string, string>();
}

(这里的名称纯粹是基于数据看起来的猜测;protobuf不传输名称—只传输数字键,即本例中的1/2/4/6)

工作当测试与:

static void Main()
{
    var encoded = Convert.FromBase64String("CjRobTovL21ldGFkYXRhL2FsYnVtL2M1MzU3MTA0M2U4ODQ3YjRhODc1YzVlNmZiNmNiZTdmEhp2bmQuc3BvdGlmeS9tZXRhZGF0YS1hbGJ1bSCQAzIYCgpNRC1WZXJzaW9uEgoxMzcwMzc5NTA1Mg8KBk1DLVRUTBIFNjk2MDQyGQoPTUMtQ2FjaGUtUG9saWN5EgZwdWJsaWMyDwoHTUMtRVRhZxIELD8q+Q==");
    MercuryReply header = ProtobufUtils.DeserializeFromBytes<MercuryReply>(encoded);
}

(使用你的DeserializeFromBytes方法)

所以:如果这对你不起作用,重要的两个问题是:

  • 实际的 base-64从你的实际代码在运行时?或者这只是你认为理论上应该的?
  • 你的MercuryReply类看起来像什么?

编辑:正如Marc Gravell在评论中指出的那样,我走错了路。请忽略我的回答,但我要离开它,因为评论讨论是有价值的。

protobuf-net与protobuf不是一回事,并且不以统一的、跨平台兼容的方式坚持算法。protobuf-net是一个基于。net契约的序列化器,它碰巧使用了protobuf,但为了互操作性的目的,它没有实现protobuf"to spec"。例如:protobuf-net知道。net类型,而Google的protobuf不知道。net类型。查看更多链接:

http://code.google.com/p/protobuf-net/wiki/GettingStarted