Reputation: 21
When develop with javascript we always need to transport json with rpc. Now I want to use json as structure member of message in grpc. Please see below:
message HelloRequest{
int32 hello = 1;
json world = 2
}
How to do that?
Upvotes: 2
Views: 9327
Reputation: 3937
If you very specifically want that JSON structure and do not care about how pretty your proto files are, you can use the google.protobuf.Struct
types to build a custom JSON structure.
https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/struct.proto
In this case, you probably want google.protobuf.ListValue
.
Upvotes: 0
Reputation: 83
Thanks to the support from community, here I'd use google.protobuf.Struct or gogo/protobuf/types/struct.pb.go
import "google/protobuf/struct.proto";
message HelloRequest{
int32 hello = 1;
google.protobuf.Struct world = 2
}
I'm currently using go v1.16 and grpc-gateway v1.16. The protoc command to gen <your_file>.pb.go should add this if you prefer gogo protobuf to google protobuf (the xx.pb.go files located in pb folder) :
--gogo_out=plugins=grpc,\
Mgoogle/protobuf/timestamp.proto=github.com/gogo/protobuf/types,\
Mgoogle/protobuf/duration.proto=github.com/gogo/protobuf/types,\
Mgoogle/protobuf/empty.proto=github.com/gogo/protobuf/types,\
Mgoogle/protobuf/struct.proto=github.com/gogo/protobuf/types,\
Mgoogle/api/annotations.proto=github.com/gogo/googleapis/google/api,\
Mgoogle/protobuf/field_mask.proto=github.com/gogo/protobuf/types:\
pb \
Last but not least, I can provide an example in which I'm using gogo protobuf. Please take a look at the code below!
import (
"github.com/gogo/protobuf/jsonpb"
"github.com/gogo/protobuf/types"
)
.....
world := &types.Struct{}
helloRequest := &pb.HelloRequest{World: world}
bts := []byte(`{"status":200,"user":{"id":1,"name":"A","age":26,"phone":null,"skills":{"backend":"Golang","frontend":"React"},"hobbies":["coding","running"]}}`)
// Every pb are proto.Message so that we have to use jsonpb package
// instead of json package
err := jsonpb.Unmarshal(bytes.NewBuffer(bts), world)
if err != nil {
panic(err)
}
The response json should be:
{
"hello": 0,
"world": {
"status": 200,
"user": {
"id": 1,
"name": "A",
"age": 26,
"phone": null,
"skills": {
"backend": "Golang",
"frontend": "React"
},
"hobbies": [
"coding",
"running"
]
}
}
}
Upvotes: 0
Reputation: 3005
There are two options to do this, depending on if you know the structure of your JSON in advance. If you do you can simply write a separate message for your JSON object and include that in your original message:
message SomeJSONMessage {
// Attributes of your JSON here
}
message HelloRequest {
int32 hello 1;
SomeJSONMessage message = 2;
}
This is possible because every JSON type maps natively to a Protobuf type.
If you do not know the structure of your JSON in advance you would have to use a google.protobuf.Struct
, which is basically a JSON without a defined structure:
message HelloRequest {
int32 hello 1;
google.protobuf.Struct message = 2;
}
This maps easily to well-known types in many programming languages (object in JS, dict in Python), but you won't have any guarantee about what attributes it contains.
Upvotes: 2