如何将含bytes类型的Protobuf消息反序列化为C#对象
Protobuf ByteString 反序列化JSON失败问题解决
问题场景
我用C# .NET Core 8.0定义了如下Protobuf对象:
syntax = "proto3"; option csharp_namespace = "Application.Messages"; message ApplicationConfig { string domain = 1; int32 port = 2; string user_name = 3; string password = 4; bytes cert = 5; }
自动生成的ApplicationConfig类包含ByteString类型的Cert属性(当前为空)。将实例序列化为JSON后得到:
{"domain":"somedomain","port":123,"userName":"Administrator","password":"888888","cert":[]}
但执行以下代码反序列化时,得到的是默认空对象,推测问题和bytes类型的cert字段有关:
var appConfig = JsonSerializer.Deserialize<ApplicationConfig>(appConfigJson);
解决方案
方案1:使用Protobuf官方JSON序列化器
Protobuf自带专门的JSON处理工具,能正确识别ByteString类型。先确保安装Google.Protobuf和Google.Protobuf.Json NuGet包,然后替换反序列化代码:
using Google.Protobuf.Json; var appConfig = JsonParser.Default.Parse<ApplicationConfig>(appConfigJson);
如果要序列化,同样用官方方法保证兼容性:
var json = JsonFormatter.Default.Format(appConfig);
方案2:为ByteString添加自定义JSON转换器
如果必须使用System.Text.Json,可以自定义转换器处理ByteString与JSON数组的转换:
using Google.Protobuf; using System.Text.Json; using System.Text.Json.Serialization; public class ByteStringJsonConverter : JsonConverter<ByteString> { public override ByteString Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType == JsonTokenType.StartArray) { var bytes = JsonSerializer.Deserialize<byte[]>(ref reader, options); return bytes == null ? ByteString.Empty : ByteString.CopyFrom(bytes); } return ByteString.Empty; } public override void Write(Utf8JsonWriter writer, ByteString value, JsonSerializerOptions options) { JsonSerializer.Serialize(writer, value.ToByteArray(), options); } }
反序列化时传入这个转换器即可:
var options = new JsonSerializerOptions(); options.Converters.Add(new ByteStringJsonConverter()); var appConfig = JsonSerializer.Deserialize<ApplicationConfig>(appConfigJson, options);
问题根源
System.Text.Json没有内置ByteString类型的转换器,默认无法将JSON数组([])映射到ByteString,导致反序列化失败,最终返回类型的默认空对象。
内容的提问来源于stack exchange,提问作者Amir M
相关产品推荐
相关产品推荐

