Protobuf.Any - 从 json.RawMessage 解组

我有来自数据库的json.RawMessage格式数据。具体的列是jsonb。


我真的找不到一种方法将数据解组到 proto 上定义为 protobuf.Any 的属性,就像这样。


repeated google.protobuf.Any list = 1;

json.Unmarshal()当我尝试使用then解组数据库中的数据时,list它是空的。文档提到了这样的事情:


foo := &pb.Foo{...}

 any, err := anypb.New(foo)

 if err != nil {

   ...

 }

 ...

 foo := &pb.Foo{}

 if err := any.UnmarshalTo(foo); err != nil {

   ...

 }

但在这个例子中是我无法转换的foo类型,因为我有.proto.Messagejson.RawMessage


有什么办法可以做到这一点?


千万里不及你
浏览 273回答 1
1回答

莫回无

首先,您应该了解 DB 列中存储的内容。json.RawMessage被简单地定义为type RawMessage []byte。而且它没有携带足够的信息来回答你的问题。我将提供一个演示来展示它是如何google.protobuf.Any工作的,这应该可以帮助您更好地理解您的问题。注意事项:Any用于在消息中嵌入其他类型。所以我在演示中 定义了另外两个消息(Foo和)。Bar消息Any类型允许您将消息用作嵌入式类型而无需其 .proto 定义。Any 包含作为字节的任意序列化消息,以及充当该消息类型的全局唯一标识符并解析为该消息类型的 URL。实际上,您的问题取决于数据库中存储的内容。请参阅 中的评论main.go。演示的文件夹结构:├── go.mod├── main.go└── pb    ├── demo.pb.go    └── demo.protogo.mod:module github.com/ZekeLu/demogo 1.19require (    github.com/golang/protobuf v1.5.2    google.golang.org/protobuf v1.28.1)pb/demo.proto:syntax = "proto3";package pb;import "google/protobuf/any.proto";option go_package = "github.com/ZekeLu/demo/pb";message MyMessage {  repeated google.protobuf.Any list = 1;}message Foo {  int32 v = 1;}message Bar {  string v = 1;}main.go:package mainimport (    "encoding/json"    "fmt"    "google.golang.org/protobuf/types/known/anypb"    "github.com/ZekeLu/demo/pb")func main() {    // If the db stores an instance of pb.Foo, then unmarshal it first.    buf := json.RawMessage([]byte(`{"v":10}`))    var foo pb.Foo    err := json.Unmarshal(buf, &foo)    if err != nil {        panic(err)    }    // And then marshal it into a new Any instance, which can be used to    // create a slice that can be assigned to pb.MyMessage.List.    a1, err := anypb.New(&foo)    if err != nil {        panic(err)    }    bar := &pb.Bar{V: "10"}    a2, err := anypb.New(bar)    if err != nil {        panic(err)    }    // Initialize the List field.    m := pb.MyMessage{List: []*anypb.Any{a1, a2}}    buf, err = json.Marshal(&m)    if err != nil {        panic(err)    }    fmt.Printf("%s\n", buf)    // Output: {"list":[{"type_url":"type.googleapis.com/pb.Foo","value":"CAo="},{"type_url":"type.googleapis.com/pb.Bar","value":"CgIxMA=="}]}    // If the db stores the output above, it can be unmarshal directly    var m2 pb.MyMessage    err = json.Unmarshal(buf, &m2)    if err != nil {        panic(err)    }    fmt.Printf("%v\n", m2.List)    // Output: [[type.googleapis.com/pb.Foo]:{v:10} [type.googleapis.com/pb.Bar]:{v:"10"}]}运行演示的步骤:$ protoc --proto_path=pb --go_out=pb --go_opt=paths=source_relative demo.proto$ go mod tidy$ go run main.go
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go