我正在尝试解析从外部服务收到的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错误。我看不出有什么理由会发生这种事。有什么明显的我没注意到吗?
这通常意味着:
- 二进制文件是无效的(人们总是把二进制文件弄得一团糟;使用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