Protobuf.js: With proto3 syntax, default values aren't being assigned

Created on 22 Apr 2017  路  2Comments  路  Source: protobufjs/protobuf.js

protobuf.js version: 6.7.0

First of all, this is a very impressive, fast library and we're looking forward to doing a lot with it, particularly with GeoJSON. Thanks!

Using proto3 syntax (which we are doing for C#/Swift use), PBFs that are encoded without default enum values are not being assigned the default value upon decoding in protobuf.js. e.g instead of:

{"precision":3,"geometry":{"type":"POINT","coords":["-112002","46587"]}}

We get:

{"precision":3,"geometry":{"coords":["-112002","46587"]}}

This is the message being used:

message Geometry {
    Type type = 1;

    repeated uint32 lengths = 2 [packed = true]; // coordinate structure in lengths
    repeated sint64 coords = 3 [packed = true]; // delta-encoded integer values
    repeated Geometry geometries = 4;

    repeated Value values = 13;
    repeated uint32 custom_properties = 15 [packed = true];

    enum Type {
        POINT = 0;
        MULTIPOINT = 1;
        LINESTRING = 2;
        MULTILINESTRING = 3;
        POLYGON = 4;
        MULTIPOLYGON = 5;
        GEOMETRYCOLLECTION = 6;
    }
}

It would be great to have a settable useDefaults attribute, perhaps when the decode method is called, e.g.

var decoded = gbData.decode(new Uint8Array(xmlhttp.response), true);

Or, if the syntax is detected as proto3 just go ahead and set the default value since that's what Google's spec calls for and it's what other languages and protoc-generated code are doing.

question

Most helpful comment

When the field is not set on the wire, its default value is still on the prototype of the created message instance:

console.log(decoded.hasOwnProperty("type"), typeof decoded.type, decoded.type);
// false, "number", 0

The reason why you are not seeing this is probably that you are just passing the message instance through JSON.stringify.

For other JavaScript-object-y things, there is Geometry.fromObject (also accepts strings for enums) and Geometry.toObject (also has a default values and an enums as strings switch). The following, for example, should output your initial message again:

JSON.stringify(Geometry.toObject(decoded, { defaults: true, enums: String }))

All 2 comments

When the field is not set on the wire, its default value is still on the prototype of the created message instance:

console.log(decoded.hasOwnProperty("type"), typeof decoded.type, decoded.type);
// false, "number", 0

The reason why you are not seeing this is probably that you are just passing the message instance through JSON.stringify.

For other JavaScript-object-y things, there is Geometry.fromObject (also accepts strings for enums) and Geometry.toObject (also has a default values and an enums as strings switch). The following, for example, should output your initial message again:

JSON.stringify(Geometry.toObject(decoded, { defaults: true, enums: String }))

Using:

var decodedObj = gbData.toObject(decoded, { defaults: true, enums: String });

The default values are now populated from the enum, whether passing a simple GeoJSON geometry or a varied FeatureCollection. This leaves us with a completely usable object. Thanks!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jarvanxing picture jarvanxing  路  4Comments

ghost picture ghost  路  3Comments

chloe2018s picture chloe2018s  路  3Comments

ArvoGuo picture ArvoGuo  路  4Comments

b1naryMan picture b1naryMan  路  4Comments