我正在尝试编写一个通用的Java类,该类可用于反序列化/解析任何protobuf消息。
以下是代码在理想环境中的外观:
public abstract class ProtoDeserializer<T extends Message> {
public T deserialize(final byte[] bytes) throws Exception {
Parser<T> parser = T.getParserForType(); // Syntax Error: this method is not static!
T message = parser.parseFrom(bytes);
validate(message);
return message;
}
public abstract void validate(final T message) throws Exception;
}
Run Code Online (Sandbox Code Playgroud)
但是,我无法获得通用protobuf消息的正确解析器。实现此类泛型类的正确方法是什么?
假设我有一个定义如下的 proto3 消息,用作 gRPC 请求(即使用 protobuf 的二进制编码):
message MyRequest {
string name = 1;
}
Run Code Online (Sandbox Code Playgroud)
我是否可以更改我的服务器(即消息的读取器)以使用以下定义而不破坏现有客户端(即写入器)的线路兼容性?
message MyRequest {
repeated string names = 1;
}
Run Code Online (Sandbox Code Playgroud)
在proto2 语言指南中,我看到以下内容:
optional兼容repeated. 给定重复字段的序列化数据作为输入,optional如果它是原始类型字段,则期望此字段的客户端将采用最后一个输入值,如果它是消息类型字段,则合并所有输入元素。
但是,proto3 文档不包含等效声明。我认为这可能与packedproto3中重复字段的编码使用有关。
Proto3不像 那样严格Proto2,并且没有requiredoroptional字段,没有自定义default值。
鉴于以下定义...
message Order {
enum Side {
BID = 0;
ASK = 1;
}
int64 time = 1;
double price = 2;
double volume = 3;
Side side = 4;
}
Run Code Online (Sandbox Code Playgroud)
这些字段中的任何一个都有默认值,毕竟现在没有规则规定您在.build()对象之前必须或不可以提供什么。
time因此is 0、priceis0.0和sideis的默认值BID,如果您打印一个没有提供其中一个字段或提供默认值的实例,那么运行时会将其视为在这两种情况下从未提供过,因此无法确定是否该值是手动设置的BID或被视为默认值。
例如,如果我们执行以下代码(其 kotlin)
Order.newBuilder()
.setPrice(1.0)
.setVolume(2.0)
.setSide(Order.Side.BID)
.build()
.apply { println(this) }
Run Code Online (Sandbox Code Playgroud)
我们将得到这个输出
price: 1.0
volume: 2.0
Run Code Online (Sandbox Code Playgroud)
至少这很烦人,因为当您使用标准.toString()或 …
Protobuf 的卖点之一是向后兼容性,即开发人员可以改进格式,而老客户端仍然可以使用它。
options现在,有了名为 proto3 的新 Protobuf 版本,IDL 语言本身不兼容,例如required删除了 enun 的新语法、无扩展等。
这是否意味着使用 proto3 无法生成较旧的 proto2 也可以读取/理解的二进制文件?
就好像你必须继续使用proto2。如果你开始使用 proto3,你就无法与旧系统对话,或者必须重写、重新编译所有这些,.proto这首先就是兼容性问题。
compatibility backwards-compatibility protocol-buffers proto3
根据以下页面,我应该能够 在“JSON 映射”下发送 json 有效负载:https : //developers.google.com/protocol-buffers/docs/proto3。
我想将 json 负载作为消息的一部分发送,我有以下 .proto 文件:
message EventsRequest{
message RequestElement {
struct payload = 1;
}
string customerId = 1;
repeated RequestElement jsonPayload = 2;
}
message EventsResponse {
int32 status = 1;
string rawResponseData = 2;
struct responseData = 3;
}
Run Code Online (Sandbox Code Playgroud)
但是编译它给了我以下错误:
[INFO] Compiling 1 proto file(s) to C:\workspace\...\target\generated-sources\protobuf\java
[ERROR] PROTOC FAILED: msg_service.proto:21:9: "struct" is not defined.
msg_service.proto:34:5: "struct" is not defined.
[ERROR] C:\workspace\...\src\main\proto\msg_service.proto [0:0]: msg_service.proto:21:9: "struct" is not defined.
msg_service.proto:34:5: …Run Code Online (Sandbox Code Playgroud) 在protobuf中,我们只能选择使用有符号或无符号的32位或64位整数来限制值的范围。
然而,我想要定义的数据结构包含 8 位、16 位和 32 位整数的混合,以节省嵌入式设备上的空间。在它们上,数据结构的实现也有些不同,并且需要为某些字段保留特殊值,因此它们的最大数量不是 2 的幂。
在这些嵌入式设备上,protobuf 定义仅用于与它们之间的传输,而不用于实际存储。所以我可以在读入它们时限制数字。
但是,我宁愿在.proto或.options文件中定义这些最大值,以确保所有客户端应用程序都了解这些限制。
有没有办法做到这一点?
我知道有字段选项,但此处列出的选项不包含此选项。可以创建自定义选项,但这似乎需要编写编译器扩展,这意味着我必须为我想要编译的每种语言手动实现此限制检查,而这会花费比节省的时间更多的时间。
我正在使用dcodeIO/protobuf.js lib(版本 6.8.4)来解析浏览器中的 protobuf 消息。只要不导入另一个原始文件,我就可以让它使用简单的原始文件。
在主文件中导入其他原始文件会破坏一切。
这就是我所拥有的:
文件结构
- assets/
|-api/
| |-v1/
| | |-messageB.proto
| |-messageA.proto
- foo.js
Run Code Online (Sandbox Code Playgroud)消息A.proto
syntax = "proto3";
package com.assets.api;
import "api/v1/messageB.proto";
message MessageA{
MessageB foo = 0;
}
Run Code Online (Sandbox Code Playgroud)messageB.proto
syntax = "proto3";
package com.assets.api.v1;
message MessageB {
string bar= 0;
}
Run Code Online (Sandbox Code Playgroud)与 6.8.4:
var MessageProto = null;
protobuf.load({root:"assets", file:"api/messageA.proto"}, function (err, root) {
if (root) { MessageAProto = root.lookupType("com.assets.api.MessageA");
}});
data = MessageProto .decode(rawData);
Run Code Online (Sandbox Code Playgroud)。
Error: no such type
at Root.lookupType (http://localhost:63342/xx/build/app/vendor/protobuf/dist/protobuf.js:3463:15) …Run Code Online (Sandbox Code Playgroud) 我正在将 json 文件转换为字符串,然后将字符串转换为 proto3 文件。
这是 json 文件:
{ "a": false,
"b": 0
}
Run Code Online (Sandbox Code Playgroud)
以下是我将 json 文件转换为字符串的方法:
String json =Files.lines(Paths.get(filePath)).collect(Collectors.joining());
Run Code Online (Sandbox Code Playgroud)
以下是将字符串转换为 proto3 文件的方法:
JsonFormat.parser().ignoringUnknownFields().merge(json,messageBuilder);
MyProto proto = messageBuilder.build();
Run Code Online (Sandbox Code Playgroud)
我的 json 中有 boolean 和 int 字段,其中一些值需要为默认值(boolean 为 false,int 为 0)。
当我将上面的文件反序列化为 proto3 java 文件时,上面的两个字段都被忽略,并且我的 json 变成空,即使我已经显式设置了值(如您在上面的 json 文件中看到的那样)。
我知道 proto3 在反序列化/序列化时忽略默认值,但是有没有办法不忽略显式设置的字段,即使它们是默认值?
我正在尝试将一些 POJO 从 Java 映射到 Protobuf (proto3)。其中一些包含列表。虽然使用 POJO 映射列表(例如 List)没有问题,但我收到了 UnsupportedOperationException。
示例List<Product>(这可以正常工作):
ProductProtobuf.Builder map(Product product);
@Mapping(target = "productsList", source = "products")
ResponseProtobuf.Builder map(Response response);
Run Code Online (Sandbox Code Playgroud)
示例List<String>(这不起作用):
@Mapping(target = "usersList", source = "users")
ResponseProtobuf.Builder map(Response response);
Run Code Online (Sandbox Code Playgroud)
另外,我有一些用于构建器的映射器:
public ResponseProtobuf.Builder responseBuilder() {
return ResponseProtobuf.newBuilder();
}
public ProductProtobuf build(ProductProtobuf.Builder builder) {
return builder.build();
}
Run Code Online (Sandbox Code Playgroud) 我是新来的 Stack Overflow,这是我的第一个问题,所以我非常开放并乐意对其进行任何改进:)当我运行与艺术品不同的测试方法时遇到问题。我有一种方法可以让用户喜欢按他们自己单独的艺术品 uuid 分类的特定艺术品,并且该方法效果很好。我有一个 console.proto 文件,在其中为 LikeArtwork 和 LikeArtwork 方法指定必要的请求和响应消息,并在methods.go 文件中创建了这些方法本身。我正在测试其他方法,除了 LikeArtwork 方法之外,它们似乎都工作得很好。
我有一个 followUser 和 UnfollowUser 方法,它们的工作方式完全相同,除了在 UnfollowUser 方法中,用户只是从包含所有关注者的“关注者”切片/数组中删除。这个概念与 likeArtwork 和 LikeArtwork 方法完全相同,其中用户从“喜欢”切片/数组中添加或删除,这就是为什么我很困惑为什么它会导致我的用户服务器因错误而崩溃:
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x2 addr=0x58 pc=0x104d0b844]
Run Code Online (Sandbox Code Playgroud)
我的console.proto定义如下:
service Service {
// Registers a user on the hockney platform/ This entails creating the user
// using the CreateUser method and uploading their profile picture using the
// UploadProfilePicture method/ Down the line, this could also …Run Code Online (Sandbox Code Playgroud)