Protobuf: The new 'Any' type and JavaScript

Created on 20 Jan 2017  路  10Comments  路  Source: protocolbuffers/protobuf

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!

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!

All 10 comments

@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!

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");
        }
    }
Was this page helpful?
0 / 5 - 0 ratings

Related issues

lostindark picture lostindark  路  148Comments

Interfere picture Interfere  路  30Comments

xfxyjwf picture xfxyjwf  路  35Comments

cl51287 picture cl51287  路  29Comments

little-dude picture little-dude  路  88Comments