簡體   English   中英

為 protobuf 消息字段定義自定義 go 結構標簽

[英]Defining custom go struct tags for protobuf message fields

我是grpc的新手,一直試圖從網絡服務器獲取json響應。 然后存根可以從rpc服務器請求json

在我的.proto文件中,我創建了一個消息類型:

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

但是我無法編組number字段,因為protoc生成帶有number標記的結構pb.go文件:

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

我如何強制使用Message字段的小寫名稱以外的標簽“轉換”消息? 比如使用json標簽no ,即使Message中的字段名是number

您可以通過設置在原消息定義一個proto3場選項json_name

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

鏈接到文檔

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 擴展的更多信息

這是我的解決方案,這是一種友好且兼容的方式,用於在 protobuf/grpc 中添加 go 結構標簽。

  1. fork protobuf-go repo 到你自己的 github 帳戶,並在 cmd/protoc-gen-go 中添加一個 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 標簽 expr。 Go tags expr 正則表達式格式為(\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 compile.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
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM