为了账号安全,请及时绑定邮箱和手机立即绑定

Protobuf.Any - 从 json.RawMessage 解组

Protobuf.Any - 从 json.RawMessage 解组

Go
千万里不及你 2023-03-15 14:49:17
我有来自数据库的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有什么办法可以做到这一点?
查看完整描述

1 回答

?
莫回无

TA贡献1865条经验 获得超7个赞

首先,您应该了解 DB 列中存储的内容。json.RawMessage被简单地定义为type RawMessage []byte。而且它没有携带足够的信息来回答你的问题。

我将提供一个演示来展示它是如何google.protobuf.Any工作的,这应该可以帮助您更好地理解您的问题。

注意事项

  1. Any用于在消息中嵌入其他类型。所以我在演示中 定义了另外两个消息(Foo和)。Bar

    消息Any类型允许您将消息用作嵌入式类型而无需其 .proto 定义。Any 包含作为字节的任意序列化消息,以及充当该消息类型的全局唯一标识符并解析为该消息类型的 URL。

  2. 实际上,您的问题取决于数据库中存储的内容。请参阅 中的评论main.go


演示的文件夹结构:

├── go.mod

├── main.go

└── pb

    ├── demo.pb.go

    └── demo.proto

go.mod:


module github.com/ZekeLu/demo


go 1.19


require (

    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 main


import (

    "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


查看完整回答
反对 回复 2023-03-15
  • 1 回答
  • 0 关注
  • 272 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号