【问题标题】:Serialization of non-required fields in protobuf-netprotobuf-net 中非必填字段的序列化
【发布时间】:2010-05-11 11:38:20
【问题描述】:

我有一个通过 ProtoBuf 序列化消息与 Google 通信的有效 Java 客户端。我目前正在尝试将该客户端翻译成 C#。

我有一个.proto 文件,其中参数appId 是一个可选字符串。它在 protobuf-net 库生成的 C# 表示中的默认值是一个空字符串,就像它在同一文件的 java 表示中一样。

message AppsRequest {
  optional AppType appType = 1;
  optional string query = 2;
  optional string categoryId = 3;
  optional string appId = 4;
  optional bool withExtendedInfo = 6;
}

我发现当我在 java 客户端中将 appId 显式设置为 "" 时,客户端停止工作(来自 Google 的 403 Bad Request)。当我在 java 客户端中将 appId 显式设置为 null 时,一切正常,但这只是因为 hasAppId 被设置为 false(我不确定这如何影响序列化)。

在 C# 客户端中,我总是收到 403 响应。我没有看到不设置值和设置默认值之间的区别背后的任何逻辑,这似乎在 java 客户端中产生了所有差异。由于输出始终是二进制流,我不确定成功的 java 消息是用空字符串序列化,还是根本不序列化。

在 C# 客户端中,我尝试在 ProtoMember 属性上将 IsRequired 设置为 true,以强制它们进行序列化,并且我尝试将默认值设置为 null,并显式设置 "",所以我很确定我已经尝试了 some 正在序列化值的配置。我也玩过ProtoBuf.ProtoIgnore,并在某些时候完全删除了appId 参数,但我无法避免C# 中的403 错误。

我已经尝试从 java 手动复制序列化字符串,这解决了我的问题,所以我确定 HTTP 请求的其余部分正在工作,并且可以将错误追溯到序列化对象。

我的连载就是这样的:

var clone = ProtoBuf.Serializer.DeepClone(request);

MemoryStream ms = new MemoryStream(2000);
ProtoBuf.Serializer.Serialize(ms, clone);

var bytearr = ms.ToArray();
string encodedData = Convert.ToBase64String(bytearr);

我承认我不太确定DeepClone 做了什么。有没有都试过了……

【问题讨论】:

    标签: c# protobuf-net protocol-buffers


    【解决方案1】:

    听起来我们想强制排除它;首先要尝试,您可以尝试在代码生成中使用“detectmissing”选项。这可以通过 IDE 和命令行实现,但有所不同(让我知道您使用的是哪个,我会添加更多内容)。

    另一个类似的选项是添加(在部分类中)bool {memberName}Specified {get;set;}。我正在查看一份涉及默认空字符串的奇怪问题的现有公开报告。

    【讨论】:

    • 为快速响应干杯。我从命令行生成了代码。 *Specified 属性似乎对结果没有影响,无论我将其设置为true 还是falseShouldSerialize* 方法也是如此,如下所示:stackoverflow.com/questions/1379332/…
    • 我在 java 序列化程序中发现了一段代码,它检查 if (hasAppId()) { output.writeString(4, getAppId()); } 所以它确实似乎完全将它从序列化输出中排除是我想要做的。
    • @David Hedlund 好的;我有你的例子 - 我会看看我能用它做什么。有关信息,您是否有一个带有 java 输出的简单数据示例,以便我确认结果?
    • @Mark Gravell:为了给您提供一些示例数据,我创建了一些简单的对象,并比较了结果。然后我注意到我对差异出现的位置是错误的。我之前被抛弃了,因为"" 是默认值,而明确设置"" 在Java 中会导致同样的错误。这是真正的交易:在 java 中设置 "" 会导致它序列化,这给了我 403。在 C# 中设置 "" 根本没有序列化,但是 another 错误一直给我 403。 C#,它一直是另一个值,默认为0,因此序列化,
    • ...应该在什么时候。我通过将其设为必填字段来解决这个问题。我接受你的回答,因为这与随后的讨论一起引导我找到了解决方案,而且,因为*Specified { get; set; } 暗示我完全不知道。非常感谢您抽出宝贵的时间(以及一个很棒的图书馆)
    猜你喜欢
    • 2020-03-29
    • 1970-01-01
    • 2014-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-26
    相关资源
    最近更新 更多