限制protobuf中的字符串长度?

Alt*_*hos 3 protocol-buffers protobuf-net protobuf-csharp-port

我正在尝试对 protobuf 消息实施限制,这些消息可以在使用不同语言的不同客户端之间共享

除此之外,我想对字符串长度实施限制,例如最小或最大长度,或者 int32 var 的最小和最大值范围

有没有办法实现这样的要求?非常感谢你的帮助!

baz*_*zza 5

这是 GPB 非常缺少的东西。Constraints可以添加到模式语言和代码生成器中,但它根本不会触及线格式。我真的非常希望 Google 能够将其添加到 GPB 中,因为那样它就接近完美了。

至此constraints,模式语言需要四个方面:

  1. 能够定义数组/列表的长度(例如字符串)
  2. 限制值范围的能力
  3. 能够将约束参数定义为常量,这些常量也内置到生成的代码中(以便程序可以知道约束是什么并在 for 循环等中使用它们)
  4. 能够根据常量参数定义约束,但 + 或 - 1(同样,为了迭代程序中的事物)

其他序列化标准确实在不同程度上支持约束,即 JSON、XML (XSD) 模式以及它们的鼻祖 ASN.1。

据我所知,JSON 模式通常用于验证 JSON 消息是否正确;但这依赖于开发人员实际将检查构建到他们的代码中。

XSD 模式原则上可以非常有用地表达约束,问题是找到实际构建有用代码的工具集。例如,Microsoft 的 XSD.exe 是一个非常原始的 XSD 代码生成器,并且完全忽略 XSD 架构中表达的任何约束。

对我来说,获胜的是 ASN.1。它很旧,但有一些非常现代的工具和线格式(是的,现在它可以使用 XML 和 JSON),支持 C、C++、C#、Java、Go、Python 以及更多,如果您仔细研究的话。ASN.1 约束满足上述所有四个功能,例如

---Define an integer constant, value 10
maxValue INTEGER ::= 360
---Define an integer message type, constrained
Bearing ::= INTEGER (0..<maxValue)
Run Code Online (Sandbox Code Playgroud)

该简短片段将为您提供 Bearing 数据类型,如果您尝试使用 0..359 范围之外的值对其进行序列化,序列化程序将返回错误(如果反序列化程序遇到格式错误的数据,反序列化程序也会返回错误)。Bearing 定义中的<是 -1,maxValue 是 360 意味着您可以编写合理的 for 循环,例如for (int az = 0; az < maxValue; az++). 在模式中定义常量非常有用,因为它是单点定义,如果您想在开发项目期间更改其值,只需在一个位置更改它并重新编译。它带来了一种非常灵活的接口定义方式。

---Length constraint
maxLen INTEGER ::= 10
---Constrained length string
Name ::= IA5STRING (SIZE(1..maxLen))
---Another constrained length string
Surname ::= IA5STRING (SIZE(1,5<..<maxLen,100))
Run Code Online (Sandbox Code Playgroud)

名称的长度必须在 1 到 10 个字符之间。姓氏长度必须为 1、6 到 9 或 100 个字符。

而且,无论你相信与否,这只是 ASN.1 中约束功能的一小部分。理论上它们还可以包含正则表达式。可以理解的是,在代码生成器中实现 ASN.1 的所有约束有点像一场噩梦,这就是为什么 ASN.1 的最佳工具是商业化的并且不是很便宜,但最终结果是涉及各种复杂的大型系统开发。语言和平台的关系非常有用。

遗憾的是,Google 协议缓冲区不执行任何此操作。

ASN.1 还允许您定义任何消息类型(INTEGER、REAL、STRING、构造的复杂类型等)的常量值。

使用 GPB 可以做的最好的事情

您对 GPB 能做的最好的事情就是注释 .proto 文件并希望开发人员阅读它。

一个技巧是故意在模式中出现语法错误,这样它就无法编译。这至少会让您的开发人员同事阅读该架构的损坏部分,并希望注意您在那里发表的任何评论。如果您想更改该值,请再次破坏架构以使他们再次读取它。

您的系统可能意味着约束可以是消息中的另一个 int 字段,并且只有系统的一部分需要设置它,并且希望系统的其余部分可以使用它。