如何在protobuf消息中表示UUID?

Edw*_*don 31 uuid protocol-buffers

我想在我的protobuf用户消息示例中将UUID附加到字段.

message User {
  // field containing id as UUID type
  required string email;
  optional string name;
}
Run Code Online (Sandbox Code Playgroud)

我知道protobuf消息还不支持UUID类型.我已经读过,最好的方法是使用UUID消息类型.

所以我猜我的用户消息将导入我的UUID消息原型定义并将其用作字段类型,如下所示:

import "myproject/UUID.proto";

message User {
  required UUID id;
  required string email;
  optional string name;
}
Run Code Online (Sandbox Code Playgroud)

我的问题是,UUID消息将如何显示,以及如何对其进行编码/解码?我的目标是Java/Scala和C#兼容性.

Ken*_*rda 34

您应该使用stringbytes代表UUID.使用string如果它是最方便的,以保持在UUID人类可读的格式(例如"de305d54-75b4-431b-adb2-eb6b9e546014"),或使用bytes,如果你存储的128位值原料.(如果你不确定,你可能想要string.)

在所调用的消息类型中包装值UUID可能有助于使代码更加自我记录,但会产生一些性能开销,并不是严格要求的.如果要执行此操作,请定义类型:

message UUID {
  required string value = 1;
}
Run Code Online (Sandbox Code Playgroud)

要么:

message UUID {
  required bytes value = 1;
}
Run Code Online (Sandbox Code Playgroud)

  • 我同意 protobuf 团队的决定。使用 `string` 或 `bytes` 来表示 UUID 很容易。添加内置类型需要在每种语言的 protobuf 实现中增加复杂性。这不值得。 (2认同)

JE4*_*E42 11

如果您想确保直接的互操作性,我建议使用字符串编码而不是字节编码:

message UUID {
  required string value = 1;
}
Run Code Online (Sandbox Code Playgroud)

字节编码的问题是:不同的 UUID 库对字节使用不同的编码/解码方案,同时它们同意如何编码/解码字符串。

例如,请参阅 C#System.guid.toBytesArray返回混合字节序格式:前三个组件是小字节序编码,而后两个是大字节序编码。

在 Java 中,Apache Commons LibraryUuid.toRawBytes以大端编码返回 uuid:

"String": 35918bc9-196d-40ea-9779-889d79b753f0
"C#"    : C9 8B 91 35 6D 19 EA 40 97 79 88 9D 79 B7 53 F0
"Java"  : 35 91 8B C9 19 6D 40 EA 97 79 88 9D 79 B7 53 F0
Run Code Online (Sandbox Code Playgroud)

附带说明一下:Python 3Uuid提供了两种编码:bytes大端编码和bytes_le混合端编码。


sw1*_*337 8

我没有足够的声望点来发表评论,所以我必须写这个作为答案。

使用字符串,而不是与其他评论者所说的不同的字节数组。根据 MS ( https://docs.microsoft.com/en-us/dotnet/architecture/grpc-for-wcf-developers/protobuf-data-types ),“不要对 Guid 值使用字节字段。问题当 Protobuf 与其他平台(例如 Java)交互时,具有字节顺序(维基百科定义)的字节序可能会导致不稳定的行为。”

  • 我很抱歉,但我一生都无法理解你的评论。 (4认同)

小智 6

如果有的话,您想使用它string来避免字节序问题。请注意,具有相同字符串表示形式(因此具有相同的“ id”)的UUID和MS GUID具有不同的字节流顺序(大端与小端)。如果您使用bytes该协议在使用UUID的Java和使用System.Guid的C#之间进行通信,则最终可能会获得翻转的ID。

  • 字节序问题仅影响16、32和64整数之类的多字节值,并在需要选择哪一端包含高阶字节的情况下进行浮点运算。对于字节数组,没有字节序,因此使用`bytes'不会引起任何字节序问题。另一方面,如果UUID以两个64位整数存储,则必须处理字节序问题。 (8认同)
  • @DougRichardson,[GUID/UUID 不仅仅是一个字节数组](https://en.wikipedia.org/wiki/Universally_unique_identifier#Format)。它具有 4/2/2/2/6 字节结构,字节顺序很重要。 (4认同)
  • @RobertTaylor在生成符合RFC 4122的UUID时是正确的,但是一旦生成UUID,就可以将其视为不透明的字节数组。要了解我的意思,请查看[Go UUID库](https://github.com/google/uuid)。版本1和版本4都创建了考虑了字节顺序的UUID,但是[编组](https://github.com/google/uuid/blob/c2e93f3ae59f2904160ceaab466009f965df46d6/marshal.go#L26)像对待简单字节数组一样对待这两个版本。由于这个问题是关于原生动物的,所以我们只关心编组方面。 (3认同)