Protobuf Any解封装

huangapple go评论96阅读模式
英文:

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

  1. 我在解组时没有提供特定的类型,因为客户端允许发送任何类型的消息,这些消息在应用程序启动时可能未定义。
  2. 因此,客户端生成一个新的 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

  1. 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.
  2. 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)
}

huangapple
  • 本文由 发表于 2022年8月17日 16:29:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/73385231.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定