grpc-node
grpc-node copied to clipboard
Working with google.protobuf.Struct
Hi, I have a gRPC server in Go with the following proto:
message Request {
google.protobuf.StringValue Id = 1;
google.protobuf.Struct Filter = 2;
}
I am writing a client in Node but I am not sure how to set the Filter field. I am using dynamic proto loading.
My imports:
const grpc = require('grpc');
const protoLoader = require('@grpc/proto-loader');
require('google-protobuf/google/protobuf/struct_pb');
I tried sending Struct field using follwoing ways: 1.
var item = new proto.google.protobuf.Struct({
fields: {
Name: {
string_value: 'name'
}
}
});
const plainObj = { 'Name':'name' };
const item = proto.google.protobuf.Struct.fromJavaScript(plainObj);
Both ways did not work. I am receiving empty value on the server.
Thanks
The google-protobuf JavaScript types are incompatible with code generated by @grpc/proto-loader. Using both here is confusing the issue.
Assuming that you are using the @grpc/proto-loader types, you should be able to represent that struct with a plain object like this:
{
fields: {
Name: {
string_value: 'name'
}
}
}
Thanks for the reply!!
I tried the solution but it didn't work.
var item = {
fields: {
Name: {
string_value: 'name'
}
}
}
let request = {Id: {value: "123"}, Filter: item}
But now I am able to receive the key but the value is empty. Server side:
fields:<key:"Name" value:<> >
Can you share your code where you are using protoLoader to load the .proto files?
Code:
const PROTO_PATH = require('path').join(__dirname, 'userprofile.proto');
const grpc = require('grpc');
const protoLoader = require('@grpc/proto-loader');
require('google-protobuf/google/protobuf/struct_pb');
const packageDefinition = protoLoader.loadSync(PROTO_PATH, { keepCase: true, longs: String, enums: String, defaults: true, oneofs: true });
const dd = grpc.loadPackageDefinition(packageDefinition).userprofile;
var ddClient = new dd.UserProfileService(
'localhost:50051',
grpc.credentials.createInsecure()
);
var item = ({
fields: {
Name: {
string_value: 'name'
}
}
})
let request = {Id: {value: "123"}, Filter: item}
ddClient.GetUserProfiles(request, function(err, response){
console.log(err)
console.log(response)
})
Any update on this issue?
Sorry, everything I see there looks right, so I don't know why it wouldn't work. It may be a bug with Protobuf.js, the protobuf runtime used by @grpc/proto-loader. Unfortunately that repository has been relatively inactive recently, but that might still be the right place for this issue.
No problem. Anyway, I ended up using static loading of proto and it is working fine for structs.
Thanks for the reply!!
I tried the solution but it didn't work.
var item = { fields: { Name: { string_value: 'name' } } } let request = {Id: {value: "123"}, Filter: item}But now I am able to receive the key but the value is empty. Server side:
fields:<key:"Name" value:<> >
I also have this problem, do you have any solution now? If there is no solution, I try to convert to string
OK, I have a slight correction to my previous suggestion: string_value should instead be stringValue. Protobuf.js loads built in google/protobuf/*.proto files differently than other proto files, and as a result, it does not apply the keepCase option and all field names are camelCased.
OK, I have a slight correction to my previous suggestion:
string_valueshould instead bestringValue. Protobuf.js loads built ingoogle/protobuf/*.protofiles differently than other proto files, and as a result, it does not apply thekeepCaseoption and all field names are camelCased.
That was exactly my case, thanks
This worked for me when I was seeing the same issue:
import { Struct } from '@bufbuild/protobuf';
Struct.fromJsonString(JSON.stringify({foo: "bar"}));