3

我正在尝试解析从外部服务收到的 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]是一个包含 protobuf 消息的 base64 字符串。示例如下所示:

CjRobTovL21ldGFkYXRhL2FsYnVtL2M1MzU3MTA0M2U4ODQ3YjRhODc1YzVlNmZiNmNiZTdmEhp2bmQuc3BvdGlmeS9tZXRhZGF0YS1hbGJ1bSCQAzIYCgpNRC1WZXJzaW9uEgoxMzcwMzc5NTA1Mg8KBk1DLVRUTBIFNjk2MDQyGQoPTUMtQ2FjaGUtUG9saWN5EgZwdWJsaWMyDwoHTUMtRVRhZxIELD8q+Q==

现在,当我运行程序时,反序列化时出现 Invalid wire-type 错误。我看不出为什么会发生这种情况。这里有什么明显的东西我错过了吗?

4

2 回答 2

4

这通常意味着:

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

根据你的二进制文件,我拼凑起来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班级是什么样的?
于 2013-06-06T08:33:57.933 回答
1

编辑:正如 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

于 2013-06-06T02:34:22.883 回答