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

I am new to grpc and have been trying to just fetch a json response from a webserver. The stub can then request the json from the rpc server.

In my .proto file, I created a message type:

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

But I am not able to marshal the number field, since protoc produces the struct pb.go file with a number tag:

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

How can I force the Message to be 'converted' with a tag other than the lowercase name of the message field? Such as using the json tag no, even if the field name in the Message is number.

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"];
}

,where:

  • no1 - new name for jsonpb marshal/unmarshal
  • no2 - new name for json marshal/unmarshal

jsonpb example:

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())
}

More information about protobuf extensions

You can set a proto3 field option on the proto message definition with a json_name

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

link to the docs