'Converting Protobuf3 with enum to JSON in Go
How can I convert grpc
/protobuf3
message to JSON
where the enum
is represented as string
?
For example, the protobuf
message:
enum Level {
WARNING = 0;
FATAL = 1;
SEVERE = 2;
...
}
message Http {
string message = 1;
Level level = 2;
}
Is converted by:
j, _ := json.MarshalIndent(protoMessage, "", "\t")
To:
{
"message": "Hello world!",
"level": 2,
}
I wish to get:
{
"message": "Hello world!",
"level": "SEVERE",
}
Thanks
Solution 1:[1]
I found out that I should use the protobuf/jsonpb
package and not the standard json
package.
so:
j, _ := json.MarshalIndent(protoMessage, "", "\t")
Should be:
m := jsonpb.Marshaler{}
result, _ := m.MarshalToString(protoMessage)
Update
As noted bellow, jsonpb
is depricated and the new solution is to use protojson
Solution 2:[2]
I found some of these modules (jsonpb) to be deprecated. What worked for me was the google encoding version:
import "google.golang.org/protobuf/encoding/protojson"
jsonString := protojson.Format(protoMessage)
Solution 3:[3]
Level is not a string though, it is an emum. There are really only two choices I see.
- Write a custom marshaller that does this for you
- Generate code that does this for you.
For #2, gogoprotobuf has an extension (still marked as experimental) that let's you do exactly this:
https://godoc.org/github.com/gogo/protobuf/plugin/enumstringer and https://github.com/gogo/protobuf/blob/master/extensions.md
Solution 4:[4]
For my use case, I wanted to write it to a file. Using the most recent packages as of this date, this was as close to a regular encoding/json
marshal as I could get.
I used the google.golang.org/protobuf/encoding/protojson
package and the .ProtoReflect().Interface()
methods of my protocol buffer data structure.
package main
import (
"io/ioutil"
"log"
"google.golang.org/protobuf/encoding/protojson"
"myproject/proto"
)
func main() {
myProtoStruct := proto.MyType{}
data, err := protojson.Marshal(myProtoStruct.ProtoReflect().Interface())
if err != nil {
log.Fatalf("Failed to JSON marhsal protobuf.\nError: %s", err.Error())
}
err = ioutil.WriteFile("my.proto.dat", data, 0600)
if err != nil {
log.Fatalf("Failed to write protobuf data to file.\nError: %s", err.Error())
}
log.Println("Written to file.")
}
Solution 5:[5]
When it comes to serialize the json object, this would be helpful.
var msg bytes.Buffer
m := jsonpb.Marshaler{}
err := m.Marshal(&msg, event)
msg.Bytes()
converts msg
to byte stream.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Evan Moran |
Solution 3 | sberry |
Solution 4 | |
Solution 5 | wthrain |