使用 C# 将 ByteString 反序列化为对象 Google.Protobuf

Deserializing ByteString into an object using C# Google.Protobuf

所以我有一条来自不同服务的 gRPC 消息(用另一种编程语言编写)。 这是这个对象的一个​​迷你版本(很明显真正的是由 protobuf 生成的)

public class Message
{
    public string Topic { get; set; }
    public string Identifier { get; set; }
    public Google.Protobuf.ByteString Msg { get; set; }
}

我的问题是应该将 ByteString 反序列化为另一个对象(也在 protobuf 文件中定义),但是当我尝试反序列化 Msg 字段时,我不断收到此错误:

Protocol message contained a tag with an invalid wire type.

和堆栈跟踪

at Google.Protobuf.UnknownFieldSet.MergeFieldFrom(CodedInputStream input) at Google.Protobuf.UnknownFieldSet.MergeGroupFrom(CodedInputStream input) at Google.Protobuf.CodedInputStream.ReadGroup(Int32 fieldNumber, UnknownFieldSet set) at Google.Protobuf.UnknownFieldSet.MergeFieldFrom(CodedInputStream input) at Google.Protobuf.UnknownFieldSet.MergeFieldFrom(UnknownFieldSet unknownFields, CodedInputStream input) at Messages.RecordingStatusChangeMessage.MergeFrom(CodedInputStream input) in C:\Users\iliaar\go\src\RecorderApp\testers\NewRecorderTester\Infra.AppDataManager\Model\Protos\Pubsub\messages.pb.cs:line 3259 at ClusterRecordersModule.RecordersViewModel.OnNewMessage(Message message) in C:\Users\iliaar\go\src\RecorderApp\testers\NewRecorderTester\ClusterRecordersModule\ViewModels\RecordersViewModel.cs:line 154

我试过调用新对象的几个方法,但都失败了 例如,我尝试使用现有实例并合并为:

innerMessageObject.MergeFrom(message.Msg.CreateCodedInput());

或使用像这样的静态解析器:

InnerMessageObject.Parser.ParseFrom(message.Msg.ToByteArray());

并且所有都失败并出现相同的错误,堆栈跟踪最终收敛到 Google.Protobuf 库中的相同位置。 我的库版本是 8.1.0 我也尝试降级到版本 6

非常感谢您的帮助。 谢谢

编辑: innerMessage 对象的结构如下:

public class InnerMessageObject
{
    public string ConfigID { get; set; }
    public bool Storage { get; set; }
    public bool Signal { get; set; }
    public string StorageTransition { get; set; }
    public string SignalTransition { get; set; }
}

此外,转换为十六进制会产生以下(有效)输出

63-6F-6E-66-69-67-5F-69-64-3A-20-37-32-30-62-66-65-34-39-2D-64-62-32-39-2D-34-35-38-33-2D-39-66-65-31-2D-65-30-32-30-37-33-32-37-39-37-39-34-0A-73-74-6F-72-61-67-65-3A-20-66-61-6C-73-65-0A-73-69-67-6E-61-6C-3A-20-66-61-6C-73-65-0A-73-74-6F-72-61-67-65-5F-74-72-61-6E-73-69-74-69-6F-6E-3A-20-22-32-30-32-30-2D-30-33-2D-30-33-54-31-32-3A-32-36-3A-34-31-2E-33-32-37-34-30-34-33-5A-22-0A-73-69-67-6E-61-6C-5F-74-72-61-6E-73-69-74-69-6F-6E-3A-20-22-32-30-32-30-2D-30-33-2D-30-33-54-31-32-3A-32-36-3A-34-31-2E-33-32-37-34-30-33-32-33-31-5A-22-0A

此外,将字节数组转换为字符串会生成具有正确数据的对象的字符串表示形式

var ba = pubsubMessage.Msg.ToByteArray();
return Encoding.UTF8.GetString(ba);

config_id: 720bfe49-db29-4583-9fe1-e02073279794 storage: false signal: false storage_transition: "2020-03-03T12:29:59.531473957Z" signal_transition: "2020-03-03T12:29:59.531473589Z"

您的负载 不是 protobuf。如果我们尝试通过 this validator,我们会看到:

63 = field 12, type StartGroup

error: Invalid wire-type; this usually means you have over-written a file without truncating or setting the length; see Using Protobuf-net, I suddenly got an exception about an unknown wire-type

所以让我们看一下前两个字节,就好像它们是 protobuf - 解码器告诉我们 0x63 是什么意思;下一个字节 0x6F 应该是一个字段头("tag");在二进制中,这是 01101111,也就是 "field 13, wire-type 7"; protobuf 中没有线类型 7。所以;解码器正确:有效载荷无效。

但并非所有都丢失了!

如果我们从所有这些 0x6* 值中猜测这可能是 ASCII 或 UTF8,并将其解码,我们得到:

config_id: 720bfe49-db29-4583-9fe1-e02073279794
storage: false
signal: false
storage_transition: "2020-03-03T12:26:41.3274043Z"
signal_transition: "2020-03-03T12:26:41.327403231Z"

这似乎是您的一些粗略的基于行的标记化格式的数据。但是:不是 protobuf。