为 protobuf 消息字段定义自定义的 Go 结构标签

14

我刚开始接触 grpc,一直在尝试从web服务器中获取一个json响应。然后存根可以请求来自rpc服务器的json

在我的.proto文件中,我创建了一个消息类型:

message Post {
    int64 number = 1;
    string now = 2;
    string name = 3;
}

但是我无法整理number字段,因为protoc会在pb.go文件中使用number标签生成结构体:

{
        "no": "23",
        "now": "12:06:46",
        "name": "bob"
}

如何强制使Message使用非小写的消息字段名称进行“转换”?比如说使用json标记no,即使在Message中该字段的名称是number

3个回答

17

您可以使用json_name在proto消息定义中设置proto3字段选项。

message Post {
    int64 number = 1 [json_name="no"];
    string now = 2;
    string name = 3;
}

文档链接


2
我已经尝试过这个,编译后的结构体字段将具有以下标签: Number string protobuf:"bytes,5,opt,name=no,json=com,proto3" json:"number,omitempty"`` - ChaChaPoly
3
.protoж–Ү件дёӯзҡ„json_nameйҖүйЎ№дёҺз”ҹжҲҗзҡ„JSONж Үзӯҫж— е…іпјҢиҖҢжҳҜдёҺе®ҳж–№protobuf-to-JSONжҳ е°„дёӯдҪҝз”Ёзҡ„еҗҚз§°жңүе…іпјҡhttps://developers.google.com/protocol-buffers/docs/proto3#jsonгҖӮиҜҘжҳ е°„е·ІеңЁjsonpbеҢ…дёӯе®һзҺ°гҖӮ - Mehran Prs
哇,你让我这一周过得非常愉快!非常感谢你。 - bullgare
1
很遗憾,我们无法真正定义实际的JSON标签。 - user17644273

12
import "github.com/gogo/protobuf/gogoproto/gogo.proto";

// Result example:
// type Post struct {
//    Number int64 `protobuf:"bytes,1,opt,name=number,json=no1,proto3" json:"no2"`
// }
message Post {
    int64 number = 1 [json_name="no1", (gogoproto.jsontag) = "no2"];
}

其中:

  • no1 - jsonpb的编组/解组新名称
  • no2 - json的编组/解组新名称

jsonpb示例:

import (
    "bytes"
    "testing"
    "encoding/json"

    "github.com/golang/protobuf/jsonpb"
    "github.com/stretchr/testify/require"
)

func TestJSON(t *testing.T) {
    msg := &Post{
        Number: 1,
    }

    buf := bytes.NewBuffer(nil)

    require.NoError(t, (&jsonpb.Marshaler{}).Marshal(buf, msg))
    require.Equal(t, `{"no1":1}`, buf.String())

    buf.Truncate(0)

    require.NoError(t, json.NewEncoder(buf).Encode(msg))
    require.Equal(t, `{"no2":1}`, buf.String())
}

关于protobuf 扩展的更多信息,请参考该链接。


-2

这是我的解决方案,它是一种友好且兼容的方式,用于在protobuf/grpc中添加go struct标签。

  1. 将protobuf-go repo fork到您自己的github帐户中,并将go tags功能添加到cmd/protoc-gen-go中。像这样:https://github.com/hacksomecn/protobuf-go/commit/2443a0ee4696acaa9aa4bf8c2e0586d7c724c645

  2. 将新功能protoc-gen-go安装到您的路径中。例如:go install github.com/hacksomecn/protobuf-go/cmd/protoc-gen-go@"v1.28.0-gotags"

  3. 使用尾注释声明消息字段,在注释中添加go tags表达式。Go tags表达式正则表达式格式为(\s?)@go_tags\(` + "(`.*`)" + `\)\s。 例如:

message HelloGoTags {
  string Name = 1; // @go_tags(`json:"name,omitempty" yaml:"name" bson:"name" db:"name" gorm:"name" validate:"required"`) awesome name
}
  1. 使用 protoc 编译 .proto 文件。例如:
protoc --go_out=. --go_opt=paths=source_relative  tags.proto
  1. 将生成带有额外标签的HelloGoTags消息。例如:
type HelloGoTags struct {
    state         protoimpl.MessageState
    sizeCache     protoimpl.SizeCache
    unknownFields protoimpl.UnknownFields

    Name string `protobuf:"bytes,1,opt,name=Name,proto3" json:"name,omitempty" gorm:"name" validate:"required" yaml:"name" bson:"name" db:"name"` // awesome name
}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接