From efd5f33e66bf78017acc8ca275389b4ef8a356ee Mon Sep 17 00:00:00 2001 From: dead-horse Date: Mon, 6 Mar 2017 12:26:45 +0800 Subject: [PATCH] [Fix] support keys starting with brackets. Relates to #200. --- lib/parse.js | 17 ++++++++++------- test/parse.js | 11 +++++------ 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/lib/parse.js b/lib/parse.js index c46202eb..f95d9f9d 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -13,6 +13,8 @@ var internals = { allowDots: false }; +var has = Object.prototype.hasOwnProperty; + internals.parseValues = function (str, options) { var obj = {}; var parts = str.split(options.delimiter, options.parameterLimit === Infinity ? undefined : options.parameterLimit); @@ -31,7 +33,7 @@ internals.parseValues = function (str, options) { var key = Utils.decode(part.slice(0, pos)); var val = Utils.decode(part.slice(pos + 1)); - if (Object.prototype.hasOwnProperty.call(obj, key)) { + if (has.call(obj, key)) { obj[key] = [].concat(obj[key]).concat(val); } else { obj[key] = val; @@ -84,26 +86,27 @@ internals.parseKeys = function (givenKey, val, options) { // The regex chunks - var parent = /^([^[]*)/; + var brackets = /(\[[^[\]]*])/; var child = /(\[[^[\]]*])/g; // Get the parent - var segment = parent.exec(key); + var segment = brackets.exec(key); + var parent = segment ? key.slice(0, segment.index) : key; // Stash the parent if it exists var keys = []; - if (segment[1]) { + if (parent) { // If we aren't using plain objects, optionally prefix keys // that would overwrite object prototype properties - if (!options.plainObjects && Object.prototype.hasOwnProperty(segment[1])) { + if (!options.plainObjects && has.call(Object.prototype, parent)) { if (!options.allowPrototypes) { return; } } - keys.push(segment[1]); + keys.push(parent); } // Loop through children appending to the array until we hit depth @@ -111,7 +114,7 @@ internals.parseKeys = function (givenKey, val, options) { var i = 0; while ((segment = child.exec(key)) !== null && i < options.depth) { i += 1; - if (!options.plainObjects && Object.prototype.hasOwnProperty.call(Object.prototype, segment[1].slice(1, -1))) { + if (!options.plainObjects && has.call(Object.prototype, segment[1].slice(1, -1))) { if (!options.allowPrototypes) { return; } diff --git a/test/parse.js b/test/parse.js index 65f6f287..35711823 100644 --- a/test/parse.js +++ b/test/parse.js @@ -399,16 +399,15 @@ test('parse()', function (t) { t.test('params starting with a closing bracket', function (st) { st.deepEqual(qs.parse(']=toString'), { ']': 'toString' }); + st.deepEqual(qs.parse(']]=toString'), { ']]': 'toString' }); + st.deepEqual(qs.parse(']hello]=toString'), { ']hello]': 'toString' }); st.end(); }); t.test('params starting with a starting bracket', function (st) { - st.deepEqual(qs.parse('[=toString'), {}); - st.end(); - }); - - t.test('params starting with a starting bracket', function (st) { - st.deepEqual(qs.parse('[=toString'), {}); + st.deepEqual(qs.parse('[=toString'), { '[': 'toString' }); + st.deepEqual(qs.parse('[[=toString'), { '[[': 'toString' }); + st.deepEqual(qs.parse('[hello[=toString'), { '[hello[': 'toString' }); st.end(); });