Hi,
I recently started using protobuf for JavaScript. I have been using protobuf for the past few years but mostly with C#/C++.
Everything seems to go well, except I was not able to find a way to work with the new 'Any' type (defined in protobuf3). I am using the binary encoding which according to the doc, should be supported in JavaScript.
I have used protoc to define the JavaScript equivalent of my proto files. I can make instances of all my types, set properties, encode them (binary), etc.
Basically, I do not seem to be able to access (see them) the Pack/Unpack functions.
Would anyone know how to do that? Any examples?
PS: I should add that my JavaScript expertise is very basic so the solution may be something obvious :)
Thanks!
@haberman
I may have found a work around.
Basically the JavaScript implementation of Any does not seem to have the Pack/Unpack functions defined. Instead I manually made instances of the Any type (where required) and then called the setType and setValue functions. I do not know if this would be acceptable...
proto:
message Message
{
Any AnyType = 1;
}
JavaScript
var message = new Message();
var value = new proto.google.protobuf.Any;
value.setValue(objectToPack.serializeBinary());
value.setTypeUrl("type.googleapis.com/FullyQualifedTypeNameOfTheObjectBeingPacked");
message.setAnyType(value);
There may be a better way of achieving this, but this worked for me.
Enjoy!
JavaScript does have pack and unpack -- see: https://github.com/google/protobuf/blob/master/src/google/protobuf/compiler/js/well_known_types/any.js
Thanks @haberman,
I think that there may be an issue with my generated code since it does not contain the pack and unpack functions. It does have the other ones though (set/getType and set/getValue).
From the source code that you linked I see that the implementation is very similar to my workaround.
I tried calling pack on one of my Any instances and I got:
"0x800a01b6 - JavaScript runtime error: Object doesn't support property or method 'pack' occurred"
Thank you
Also, note that when generating the code, I have followed the instructions documented here for CommonJS:
https://github.com/google/protobuf/tree/master/js
$ protoc --js_out=import_style=commonjs,binary:. messages.proto base.proto
After that I browserify it (since the current protoc does not support generating browser targeted files -- well it does define support for browsers but it does not implement it -- see https://github.com/google/protobuf/issues/2556)
The resulting file does not seem to contain the pack/unpack functions...(unless I am doing something wrong). If I am right (and there is a good chance that I am doing something wrong), there may be an issue with the code generator.
I should have mentioned that the well-known type support is not currently released (it's only on GitHub) but will be part of the upcoming 3.2 release.
Aha! :)
OK, thank you for your time! I will use my workaround until then.
This was released as part of 3.2! Resolving this issue.
@cristianmad @haberman
Can you please kindly share the updated solution for using protobuf.Any in javascript.
Here's an example of deserializing an any. Couldn't find the pack/unpack methods.
/**
* @param {!proto.google.protobuf.Any} any
*/
handleAny(any) {
switch (any.getTypeUrl()) {
case "type.example.com/package_name.Special":
const special = Special.deserializeBinary(any.getValue());
this.handleSpecial(special);
default:
console.warn("Don't know how to deal with this any type");
}
}
Most helpful comment
I may have found a work around.
Basically the JavaScript implementation of Any does not seem to have the Pack/Unpack functions defined. Instead I manually made instances of the Any type (where required) and then called the setType and setValue functions. I do not know if this would be acceptable...
proto:
message Message
{
Any AnyType = 1;
}
JavaScript
var message = new Message();
var value = new proto.google.protobuf.Any;
value.setValue(objectToPack.serializeBinary());
value.setTypeUrl("type.googleapis.com/FullyQualifedTypeNameOfTheObjectBeingPacked");
message.setAnyType(value);
There may be a better way of achieving this, but this worked for me.
Enjoy!