Protobuf.js: snake_case properties are silently dropped.

Created on 18 Aug 2017  路  4Comments  路  Source: protobufjs/protobuf.js

protobuf.js version: 6.8.0

Encoding a valid, plain object with snake_case properties causes those properties to be dropped when encoding. If camelCase is used, everything works as expected.

Minimal snippet of JS below:

protobuf.load(`${__dirname}/test2.proto`)
.then(function(root) {

    const LocationUpdateEvent = root.lookupType('LocationServiceLocationUpdateV1');

    const examplePayload = {
        user_id: 'a user ID',
        requestId: 'a request ID'
    };

    var errMsg = LocationUpdateEvent.verify(examplePayload);
    if (errMsg){
        console.error(errMsg);
        throw Error(errMsg);
    }

    const lue = LocationUpdateEvent.create(examplePayload);
    console.log('lue', lue, '\n');
    // logs `lue LocationServiceLocationUpdateV1 { user_id: 'a user ID', requestId: 'a request ID' }`

    const buf = LocationUpdateEvent.encode(lue).finish();
    console.log('buf', buf, '\n');
    // logs `buf <Buffer 12 0c 61 20 72 65 71 75 65 73 74 20 49 44>`

    const returnedLue = LocationUpdateEvent.decode(buf);
    console.log('returnedLue', returnedLue, '\n');
    // logs `returnedLue LocationServiceLocationUpdateV1 { requestId: 'a request ID' }`
    // notice, `user_id` is missing!
    console.log('keys', Object.keys(returnedLue), '\n');
    // logs `keys [ 'requestId' ]`, just a sanity check

    const backInJson = LocationUpdateEvent.toObject(returnedLue);
    console.log('backInJson', backInJson, '\n');
    // logs `backInJson { requestId: 'a request ID' }`. One property got lost.
});

Definition from test2.proto:

syntax = "proto3";

message LocationServiceLocationUpdateV1 {

    string user_id = 1;
    string requestId = 2;
}

Most helpful comment

The default is camel case because that's the more JavaScripty-notation and because Google's official library is doing the same.

There is also an option to retain snake case when using Root#load:

var root = new Root();
root.load("someFile,proto", { keepCase: true }).then(() => {
  ...
});

There's an equal option for pbjs as well.

Not a fan of adding (most of the time redundant) assertions for the respective incorrect opposite there.

All 4 comments

I just ran into this. noticed afterwards that the examples mention that awesome_field becomes awesomeField. any reason in particular for this mapping? would it make sense to error instead of dropping data silently?

The default is camel case because that's the more JavaScripty-notation and because Google's official library is doing the same.

There is also an option to retain snake case when using Root#load:

var root = new Root();
root.load("someFile,proto", { keepCase: true }).then(() => {
  ...
});

There's an equal option for pbjs as well.

Not a fan of adding (most of the time redundant) assertions for the respective incorrect opposite there.

thanks for the clarification

This makes sense. I missed the line in the docs that shows awesome_field // becomes awesome_field. Thanks very much :)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

asafcombo picture asafcombo  路  4Comments

spiderkeys picture spiderkeys  路  5Comments

ghost picture ghost  路  3Comments

terranmoccasin picture terranmoccasin  路  5Comments

kostyay picture kostyay  路  3Comments