Reputation: 798
I have a TypeScript server trying to read a JSON object using a Struct but it seems to be partially working only for objects containing a "fields" key which then expects an object as value. Nonetheless, a Struct should work with any JSON object.
Using BloomRPC I am trying the following message:
{
"payload": {
"fields": {
"Hello": {
"whatever": 0
}
}
}
}
The server reads:
{ fields: { Hello: {} } }
If I send:
{
"payload": {
"anotherfield": {
"HelloWorld": {
"whatever": 0
}
}
}
}
I get an empty object on the server.
The simplified protobuf file looks like this:
syntax = "proto3";
import "google/protobuf/struct.proto";
// The service definition.
service TestTicketService {
rpc UpdateTicket (UpdateTicketRequest) returns (UpdateTicketResponse);
}
// The request message containing the required ticket information.
message UpdateTicketRequest {
string ticketId = 1;
google.protobuf.Struct payload = 2;
}
// The response message containing any potential error message
message UpdateTicketResponse {
string error = 1;
}
Any idea why google/protobuf/struct.proto doesn't work as expected?
Upvotes: 3
Views: 9163
Reputation: 1509
First, install @types/google-protobuf
and:
let rqm = new UpdateTicketRequest();
rqm.setTicketId("1");
rqm.setPayload(Struct.fromJavaScript({
Hello:{
whatever: 0,
}
});
//and call the api....
UpdateTicket(rqm);
Upvotes: 2
Reputation: 750
The idea of a struct is that you can store arbitrary data - but only simple types: null, number, string, bool, array and object.
This maps perfectly to JSON, and this is not by accident. The google.protobuf.Struct message has a special JSON representation:
The JSON representation for
Struct
is JSON object.
So you can parse any JSON string into a protobuf Struct, and when serializing to JSON again, you also get the same JSON string again.
It is important to note that the in-memory representation of the parsed Struct is not equal to a JSON object. Protobuf does not have dynamic fields and has to represent JSON data in a more complicated manner. That is why struct.proto defines some other types.
When you want to create a Struct in JavaScript, it is probably the easiest way to just create the JSON object you want:
var jsonObject = {foo: "bar"};
var jsonString = JSON.stringify(jsonObject);
Now you can parse you Struct from this jsonObject or jsonString and put set resulting Struct as a field value in another protobuf message.
Since you are already using TypeScript, it might be worth checking out one of the alternative TypeScript implementations for protobuf. I am the author of protobuf-ts. Creating a Struct is pretty straight-forward:
let struct = Struct.fromJson({foo: "bar"});
Upvotes: 3
Reputation: 798
What really confused me is that I was trying to pass normal JSON objects and expecting to read them. The whole point is that from the client side, the JSON object needs to be encoded in a very specific way.
For example:
"payload": {
"fields": {
"name": {
"stringValue": "joe"
},
"age": {
"numberValue": 28
}
}
}
You can figure out the format of the message by looking at the Struct proto file here: https://googleapis.dev/nodejs/asset/latest/v1_doc_google_protobuf_doc_struct.js.html
Upvotes: 5