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

标签 c# deserialization protocol-buffers

所以我有一条来自不同服务的 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

我真的很感激一些帮助。 谢谢

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

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 应该是字段头(“标签”);二进制为 01101111,即“字段 13,线路类型 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。

关于c# - 使用 C# Google.Protobuf 将 ByteString 反序列化为对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60505749/

相关文章:

byte - protobuf 3.0 中的 any 和 bytes 有什么区别?

c# - 线程和 UI C# 之间的共享变量

c# - 提高性能但需要维护的计算字段 (EF)

c# - ASP.NET - App_Code - 在同一文件夹中混合 VB 和 C#

c# - 在 C# 中从 base64 反序列化对象

docker - 未定义 : grpc. SupportPackageIsVersion7 grpc.ServiceRegistrar

c - protobuf c 字符串解码

c# - C# 使用 AES 对 Java 加密/解密的奇怪行为

java - 如何从java应用程序序列化和在android上反序列化?

c++ - 结构中浮点 vector 的序列化