Reputation: 6295
Is there a good way to get a human readable string representation of protobuf objects in golang? Something equivalent to https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.message#Message.DebugString?
I am using https://github.com/golang/protobuf.
Upvotes: 12
Views: 22733
Reputation: 63
Since github.com/golang/protobuf is now deprecated, I'm writing this answer for the package google.golang.org/protobuf as it might help new readers.
The prototext package is aimed to convert messages to and from text format. The output is human readable. Using the same example from other answers:
p := &example.Test{
Label: proto.String("this"),
Reps: []int64{4, 3, 2, 1},
InnerTest: &example.Test_InnerTest{
InnerLabel: proto.String("is the end"),
},
}
fmt.Println(prototext.Format(p))
However, I suggest using the protojson package since its outputs are also human readable and it has more options available. For instance, if you want to output all the fields of the message, even those that were not populated, in a human readable manner you can do
p := &example.Test{
Label: proto.String("this"),
Reps: []int64{4, 3, 2, 1},
InnerTest: &example.Test_InnerTest{
InnerLabel: proto.String("is the end"),
},
}
fmt.Println(
protojson.MarshalOptions{
Multiline: true,
EmitUnpopulated: true,
}.Format(p)
)
Upvotes: 1
Reputation: 1
Example one:
package main
import "google.golang.org/protobuf/types/known/structpb"
func example1(x *structpb.Struct) string {
return x.String()
}
Example two:
package main
import (
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/runtime/protoimpl"
)
func example2(m proto.Message) string {
return protoimpl.X.MessageStringOf(m)
}
Example three:
package main
import (
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/proto"
)
func example3(m proto.Message) string {
return protojson.Format(m)
}
Test:
package main
import "google.golang.org/protobuf/types/known/structpb"
func main() {
m, err := structpb.NewStruct(map[string]interface{}{
"month": 12, "day": 31,
})
if err != nil {
panic(err)
}
println(example1(m))
println(example2(m))
println(example3(m))
}
Result:
fields:{key:"day" value:{number_value:31}} fields:{key:"month" value:{number_value:12}}
fields:{key:"day" value:{number_value:31}} fields:{key:"month" value:{number_value:12}}
{
"day": 31,
"month": 12
}
Upvotes: 4
Reputation: 1147
You can use MarshalToString, if you need to marshal your PB into a structured message(in JSON) for future use.
A simple example:
marshaler := &jsonpb.Marshaler{}
reqString, err := marshaler.MarshalToString(req)
log.Println("@@REQ@@", reqString)
Or refer to official unit test is ok.
Upvotes: 1
Reputation: 286
I believe you're looking for proto.MarshalTextString.
p := &example.Test{
Label: proto.String("this"),
Reps: []int64{4, 3, 2, 1},
InnerTest: &example.Test_InnerTest{
InnerLabel: proto.String("is the end"),
},
}
fmt.Println(proto.MarshalTextString(p))
You can see an example in the Go package test.
Upvotes: 19
Reputation: 182664
You can use the TextMarshaler. With a slightly modified example proto:
p := &example.Test{
Label: proto.String("this"),
Reps: []int64{4, 3, 2, 1},
InnerTest: &example.Test_InnerTest{
InnerLabel: proto.String("is the end"),
},
}
t := proto.TextMarshaler{}
t.Marshal(os.Stdout, p)
Outputs:
label: "this"
reps: 4
reps: 3
reps: 2
reps: 1
inner_test: <
inner_label: "is the end"
>
Upvotes: 4