grpc-node icon indicating copy to clipboard operation
grpc-node copied to clipboard

Working with google.protobuf.Struct

Open kpiyush17 opened this issue 5 years ago • 11 comments

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

kpiyush17 avatar Feb 12 '20 12:02 kpiyush17

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'
    }
  }
}

murgatroid99 avatar Feb 12 '20 17:02 murgatroid99

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:<> >

kpiyush17 avatar Feb 12 '20 18:02 kpiyush17

Can you share your code where you are using protoLoader to load the .proto files?

murgatroid99 avatar Feb 12 '20 18:02 murgatroid99

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)
})

kpiyush17 avatar Feb 12 '20 18:02 kpiyush17

Any update on this issue?

kpiyush17 avatar Feb 13 '20 14:02 kpiyush17

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.

murgatroid99 avatar Feb 13 '20 18:02 murgatroid99

No problem. Anyway, I ended up using static loading of proto and it is working fine for structs.

kpiyush17 avatar Feb 14 '20 08:02 kpiyush17

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

huangxinrui avatar Sep 08 '21 09:09 huangxinrui

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.

murgatroid99 avatar Sep 08 '21 18:09 murgatroid99

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.

That was exactly my case, thanks

gabrielrra avatar Jun 07 '22 14:06 gabrielrra

This worked for me when I was seeing the same issue:

import { Struct } from '@bufbuild/protobuf';

Struct.fromJsonString(JSON.stringify({foo: "bar"}));

joeyagreco-sb avatar Feb 14 '24 03:02 joeyagreco-sb