diff --git a/lib/parse.js b/lib/parse.js index 9adad86e..e3c382ca 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -60,6 +60,8 @@ var charsetSentinel = 'utf8=%E2%9C%93'; // encodeURIComponent('✓') var parseValues = function parseQueryStringValues(str, options) { var obj = { __proto__: null }; + var keysByRoot = options.duplicates === 'last' ? { __proto__: null } : undefined; + var cleanStr = options.ignoreQueryPrefix ? str.replace(/^\?/, '') : str; cleanStr = cleanStr.replace(/%5B/gi, '[').replace(/%5D/gi, ']'); @@ -131,8 +133,25 @@ var parseValues = function parseQueryStringValues(str, options) { } if (key !== null) { + if (options.duplicates === 'last') { + var keyIsArray = key.indexOf('[') !== -1; + var root = keyIsArray ? key.split('[')[0] : key; + var existingKeys = keysByRoot[root]; + if (!existingKeys) { + keysByRoot[root] = [key]; + } else if (existingKeys[0].indexOf('[') !== -1 === keyIsArray) { + existingKeys.push(key); + } else { + for (var j = 0; j < existingKeys.length; j++) { + delete obj[existingKeys[j]]; + } + keysByRoot[root] = [key]; + } + } + var existing = has.call(obj, key); - if (existing && options.duplicates === 'combine') { + if (existing && (options.duplicates === 'combine' + || (options.duplicates === 'last' && key !== null && key.indexOf('[]') !== -1))) { obj[key] = utils.combine(obj[key], val); } else if (!existing || options.duplicates === 'last') { obj[key] = val;