如何在 protobuf 消息中表示 UUID?
How do I represent a UUID in a protobuf message?
我想将 UUID 附加到我的 protobuf 用户消息示例中的字段。
message User {
// field containing id as UUID type
required string email;
optional string name;
}
我知道protobuf消息还不支持UUID类型。我读过最好的方法是使用 UUID 消息类型。
所以我猜我的用户消息会导入我的 UUID 消息原型定义并将其用作字段类型,如下所示:
import "myproject/UUID.proto";
message User {
required UUID id;
required string email;
optional string name;
}
我的问题是,UUID 消息将如何显示,我将如何 encode/decode 它?我的目标是 Java/Scala 和 C# 兼容性。
您可能应该使用 string
或 bytes
来表示 UUID。如果将 UUID 保持为人类可读的格式(例如 "de305d54-75b4-431b-adb2-eb6b9e546014"
)最方便,请使用 string
,如果要存储 128 位原始值,请使用 bytes
。 (如果您不确定,您可能想要 string
。)
将值包装在名为 UUID
的消息类型中有助于使代码更加自我记录,但会产生一些性能开销,因此并非严格要求。如果你想这样做,定义类型如下:
message UUID {
required string value = 1;
}
或:
message UUID {
required bytes value = 1;
}
如果有的话,您想使用 string
来避免字节顺序问题。请注意,具有相同字符串表示形式(因此相同 "id")的 UUID 和 MS GUID 具有不同的字节流顺序(big-endian 与 little-endian)。如果您在协议中使用 bytes
在使用 UUID 的 Java 和使用 System.Guid 的 C# 之间进行通信,您最终可能会得到颠倒的 ID。
我没有足够的声誉点数来发表评论,所以我必须写这个作为答案。
使用字符串,而不是字节数组,这与其他一些评论者所说的不同。根据 MS (https://docs.microsoft.com/en-us/dotnet/architecture/grpc-for-wcf-developers/protobuf-data-types),“不要为 Guid 值使用字节字段。当 Protobuf 与其他平台交互时,字节顺序问题(维基百科定义)可能导致不稳定的行为,例如 Java ."
如果您想确保直接的互操作性,我建议使用字符串编码而不是字节编码:
message UUID {
required string value = 1;
}
字节编码的问题是:不同的 UUID 库对字节使用不同的 encoding/decoding 方案,但它们同意如何 encode/decode 字符串。
例如,请参阅 C# 的 System.guid.toBytesArray
returns 混合端格式:前三个组件采用小端编码,而后两个组件采用大端编码。
在Java中,Apache Commons Library Uuid.toRawBytes
returns大端编码的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
附带说明:Python 3 的 Uuid
提供两种编码:bytes
用于大端编码,bytes_le
用于混合端编码。
我想将 UUID 附加到我的 protobuf 用户消息示例中的字段。
message User {
// field containing id as UUID type
required string email;
optional string name;
}
我知道protobuf消息还不支持UUID类型。我读过最好的方法是使用 UUID 消息类型。
所以我猜我的用户消息会导入我的 UUID 消息原型定义并将其用作字段类型,如下所示:
import "myproject/UUID.proto";
message User {
required UUID id;
required string email;
optional string name;
}
我的问题是,UUID 消息将如何显示,我将如何 encode/decode 它?我的目标是 Java/Scala 和 C# 兼容性。
您可能应该使用 string
或 bytes
来表示 UUID。如果将 UUID 保持为人类可读的格式(例如 "de305d54-75b4-431b-adb2-eb6b9e546014"
)最方便,请使用 string
,如果要存储 128 位原始值,请使用 bytes
。 (如果您不确定,您可能想要 string
。)
将值包装在名为 UUID
的消息类型中有助于使代码更加自我记录,但会产生一些性能开销,因此并非严格要求。如果你想这样做,定义类型如下:
message UUID {
required string value = 1;
}
或:
message UUID {
required bytes value = 1;
}
如果有的话,您想使用 string
来避免字节顺序问题。请注意,具有相同字符串表示形式(因此相同 "id")的 UUID 和 MS GUID 具有不同的字节流顺序(big-endian 与 little-endian)。如果您在协议中使用 bytes
在使用 UUID 的 Java 和使用 System.Guid 的 C# 之间进行通信,您最终可能会得到颠倒的 ID。
我没有足够的声誉点数来发表评论,所以我必须写这个作为答案。
使用字符串,而不是字节数组,这与其他一些评论者所说的不同。根据 MS (https://docs.microsoft.com/en-us/dotnet/architecture/grpc-for-wcf-developers/protobuf-data-types),“不要为 Guid 值使用字节字段。当 Protobuf 与其他平台交互时,字节顺序问题(维基百科定义)可能导致不稳定的行为,例如 Java ."
如果您想确保直接的互操作性,我建议使用字符串编码而不是字节编码:
message UUID {
required string value = 1;
}
字节编码的问题是:不同的 UUID 库对字节使用不同的 encoding/decoding 方案,但它们同意如何 encode/decode 字符串。
例如,请参阅 C# 的 System.guid.toBytesArray
returns 混合端格式:前三个组件采用小端编码,而后两个组件采用大端编码。
在Java中,Apache Commons Library Uuid.toRawBytes
returns大端编码的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
附带说明:Python 3 的 Uuid
提供两种编码:bytes
用于大端编码,bytes_le
用于混合端编码。