英文:
Protobuf Any unmarshal
问题
我有一个使用 Any 类型的原型 API。
message Document {
DocumentMeta meta = 1;
bytes data = 2;
google.protobuf.Any details = 3;
}
在客户端,我创建了一个名为 Dog 的消息,并将 details 字段设置如下:
dog1 := events2.Dog{
Name: "Leo",
Id: 1,
}
var dst anypb.Any
err = anypb.MarshalFrom(&dst, &dog1, proto.MarshalOptions{})
包含 Dog proto 的 .pb 文件也被复制到服务器上。
如果我在服务器上打印 Document,它会给出正确的信息:
Any: type_url: "type.googleapis.com/com.test.eventbus.pb.events.Dog" value: "\n\x03Leo\x10\x01"
在服务器端,我在不提供特定 proto.Message 类型(Dog)的情况下进行解组:
basicDog, err := anypb.UnmarshalNew(doc.GetDetails(), proto.UnmarshalOptions{})
解组失败,显示 proto: not found
。
- 我在解组时没有提供特定的类型,因为客户端允许发送任何类型的消息,这些消息在应用程序启动时可能未定义。
- 因此,客户端生成一个新的 proto 文件,为 Go 生成 .pb 文件,并将此 .go 文件复制到服务器上。
在使用 unmarshalAny() 方法时,我该如何在服务器端使用 .pb 文件?
英文:
I have a proto API using Any type
message Document {
DocumentMeta meta = 1;
bytes data = 2;
google.protobuf.Any details = 3;
}
On client, I have created a message named Dog and I create the details field as follows:
dog1 := events2.Dog{
Name: "Leo",
Id: 1,
}
var dst anypb.Any
err = anypb.MarshalFrom(&dst, &dog1, proto.MarshalOptions{})
The .pb file containing Dog proto is copied in the server also.
If I print the Document in Server, it gives correct information
Any:type_url:"type.googleapis.com/com.test.eventbus.pb.events.Dog" value:"\n\x03Leo\x10\x01"
On Server-side, I am unmarshalling without providing a specific proto.Message type(Dog)
basicDog, err := anypb.UnmarshalNew(doc.GetDetails(), proto.UnmarshalOptions{})
The UnmarshalNew fails with proto: not found
- I am not providing a specific type during unmarshalling since clients are allowed to send any type of message which may not be defined during application startup time.
- So the client generates a new proto file, generates .pb for go and copies this .go file inside the server.
How can I use .pb file on server-side while using unmarshalAny() method?
答案1
得分: 2
尝试使用google.protobuf.Value
。
Proto文件:
syntax = "proto3";
package mediation.common;
option go_package = ".;common";
import "google/protobuf/struct.proto";
message Model {
google.protobuf.Value any = 2;
}
使用:
package common
import (
"encoding/json"
"testing"
"google.golang.org/protobuf/types/known/structpb"
)
type Dog struct {
Id int
Name string
}
func TestAny(t *testing.T) {
data := map[string]interface{}{
"id": 1,
"name": "kitty",
}
s, _ := structpb.NewValue(data)
newData := s.GetStructValue()
m := Model{Any: structpb.NewStructValue(newData)}
var dog Dog
unmarshal(m.GetAny(), &dog)
t.Log(dog)
var mm map[string]interface{}
unmarshal(m.GetAny(), &mm)
t.Log(mm)
}
func unmarshal(p *structpb.Value, o interface{}) error {
byt, _ := p.MarshalJSON()
return json.Unmarshal(byt, o)
}
以上是代码的翻译部分。
英文:
Try use google.protobuf.Value
Proto file:
syntax = "proto3";
package mediation.common;
option go_package = ".;common";
import "google/protobuf/struct.proto";
message Model {
google.protobuf.Value any = 2;
}
using:
package common
import (
"encoding/json"
"testing"
"google.golang.org/protobuf/types/known/structpb"
)
type Dog struct {
Id int
Name string
}
func TestAny(t *testing.T) {
data := map[string]interface{}{
"id": 1,
"name": "kitty",
}
s, _ := structpb.NewValue(data)
newData := s.GetStructValue()
m := Model{Any: structpb.NewStructValue(newData)}
var dog Dog
unmarshal(m.GetAny(), &dog)
t.Log(dog)
var mm map[string]interface{}
unmarshal(m.GetAny(), &mm)
t.Log(mm)
}
func unmarshal(p *structpb.Value, o interface{}) error {
byt, _ := p.MarshalJSON()
return json.Unmarshal(byt, o)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论