From 5f9bede280aa998afb7898e8d2718b4a229e8e6f Mon Sep 17 00:00:00 2001 From: Conor Branagan Date: Wed, 14 Dec 2016 17:07:17 -0500 Subject: [PATCH] Fix asJSON defaults option, make it work for repeated fields. Fixing two issues in here: 1. When the `defaults` option was enabled, we were using `Object.keys(this)` which ends up returning an array that includes things like `$root` and asJSON. Instead we can use the `fields` we already have available. 2. For repeated values we were not setting the empty list default because the length check would break earlier. We're now passing through when the defaults option is set as well. Added a test on this stuff as well. --- src/message.js | 8 +++----- tests/data/message.proto | 8 ++++++++ tests/message.js | 25 +++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 5 deletions(-) create mode 100644 tests/data/message.proto create mode 100644 tests/message.js diff --git a/src/message.js b/src/message.js index 2580f1b8a..ccae7f0cf 100644 --- a/src/message.js +++ b/src/message.js @@ -3,7 +3,7 @@ module.exports = Message; /** * Constructs a new message instance. - * + * * This method should be called from your custom constructors, i.e. `Message.call(this, properties)`. * @classdesc Abstract runtime message. * @extends {Object} @@ -46,9 +46,7 @@ MessagePrototype.asJSON = function asJSON(options) { json = {}; var keys; if (options.defaults) { - keys = []; - for (var k in this) // eslint-disable-line guard-for-in - keys.push(k); + keys = Object.keys(fields); } else keys = Object.keys(this); for (var i = 0, key; i < keys.length; ++i) { @@ -56,7 +54,7 @@ MessagePrototype.asJSON = function asJSON(options) { value = this[key]; if (field) { if (field.repeated) { - if (value && value.length) { + if (value && (value.length || options.defaults)) { var array = new Array(value.length); for (var j = 0, l = value.length; j < l; ++j) array[j] = field.jsonConvert(value[j], options); diff --git a/tests/data/message.proto b/tests/data/message.proto new file mode 100644 index 000000000..c9f7d97b2 --- /dev/null +++ b/tests/data/message.proto @@ -0,0 +1,8 @@ +syntax = "proto3"; + +package test; + +message TestRepeatedDefaults { + required string aString = 1; + repeated string repeatString = 2; +} diff --git a/tests/message.js b/tests/message.js new file mode 100644 index 000000000..c6936a738 --- /dev/null +++ b/tests/message.js @@ -0,0 +1,25 @@ +var tape = require("tape"); +var protobuf = require(".."); + +tape.test("test asJSON repeated defaults", function(test) { + + protobuf.load("tests/data/message.proto", function(err, root) { + if (err) + return test.fail(err.message); + test.ok(true, "should parse without errors"); + + var TestMessage = root.lookup("test.TestRepeatedDefaults"); + var msg1 = TestMessage.create({ aString: 'foo' }); + + var defaultsOn = msg1.asJSON({ defaults: true }); + test.equal(defaultsOn.aString, 'foo', "should set aString value"); + test.same(defaultsOn.repeatString, [], "should set repeated default"); + + var defaultsOff = msg1.asJSON({ defaults: false }); + test.equal(defaultsOff.aString, 'foo', "should set aString value"); + test.same(defaultsOff.repeatString, undefined, "should not set repeated default"); + + test.end(); + }); + +});