Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[New] Prefix option for parse function #213

Merged
merged 1 commit into from Jun 13, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions .eslintrc
Expand Up @@ -4,12 +4,12 @@
"extends": "@ljharb",

"rules": {
"complexity": [2, 26],
"complexity": [2, 27],
"consistent-return": 1,
"id-length": [2, { "min": 1, "max": 25, "properties": "never" }],
"indent": [2, 4],
"max-params": [2, 12],
"max-statements": [2, 43],
"max-statements": [2, 44],
"no-continue": 1,
"no-magic-numbers": 0,
"no-restricted-syntax": [2, "BreakStatement", "DebuggerStatement", "ForInStatement", "LabeledStatement", "WithStatement"],
Expand Down
13 changes: 13 additions & 0 deletions README.md
Expand Up @@ -118,6 +118,13 @@ var limited = qs.parse('a=b&c=d', { parameterLimit: 1 });
assert.deepEqual(limited, { a: 'b' });
```

To bypass the leading question mark, use `ignoreQueryPrefix`:

```javascript
var prefixed = qs.parse('?a=b&c=d', { ignoreQueryPrefix: true });
assert.deepEqual(prefixed, { a: 'b', c: 'd' });
```

An optional delimiter can also be passed:

```javascript
Expand Down Expand Up @@ -323,6 +330,12 @@ Properties that are set to `undefined` will be omitted entirely:
assert.equal(qs.stringify({ a: null, b: undefined }), 'a=');
```

The query string may optionally be prepended with a question mark:

```javascript
assert.equal(qs.stringify({ a: 'b', c: 'd' }, { addQueryPrefix: true }), '?a=b&c=d');
```

The delimiter may be overridden with stringify as well:

```javascript
Expand Down
5 changes: 4 additions & 1 deletion lib/parse.js
Expand Up @@ -18,7 +18,9 @@ var defaults = {

var parseValues = function parseQueryStringValues(str, options) {
var obj = {};
var parts = str.split(options.delimiter, options.parameterLimit === Infinity ? undefined : options.parameterLimit);
var cleanStr = options.ignoreQueryPrefix ? str.replace(/^\?/, '') : str;
var limit = options.parameterLimit === Infinity ? undefined : options.parameterLimit;
var parts = cleanStr.split(options.delimiter, limit);

for (var i = 0; i < parts.length; ++i) {
var part = parts[i];
Expand Down Expand Up @@ -136,6 +138,7 @@ module.exports = function (str, opts) {
throw new TypeError('Decoder has to be a function.');
}

options.ignoreQueryPrefix = options.ignoreQueryPrefix === true;
options.delimiter = typeof options.delimiter === 'string' || utils.isRegExp(options.delimiter) ? options.delimiter : defaults.delimiter;
options.depth = typeof options.depth === 'number' ? options.depth : defaults.depth;
options.arrayLimit = typeof options.arrayLimit === 'number' ? options.arrayLimit : defaults.arrayLimit;
Expand Down
4 changes: 3 additions & 1 deletion lib/stringify.js
Expand Up @@ -203,5 +203,7 @@ module.exports = function (object, opts) {
));
}

return keys.join(delimiter);
var prefix = options.addQueryPrefix === true ? '?' : '';

return prefix + keys.join(delimiter);
};
7 changes: 7 additions & 0 deletions test/parse.js
Expand Up @@ -305,6 +305,13 @@ test('parse()', function (t) {
st.end();
});

t.test('allows for query string prefix', function (st) {
st.deepEqual(qs.parse('?foo=bar', { ignoreQueryPrefix: true }), { foo: 'bar' });
st.deepEqual(qs.parse('foo=bar', { ignoreQueryPrefix: true }), { foo: 'bar' });
st.deepEqual(qs.parse('?foo=bar', { ignoreQueryPrefix: false }), { '?foo': 'bar' });
st.end();
});

t.test('parses an object', function (st) {
var input = {
'user[name]': { 'pop[bob]': 3 },
Expand Down
5 changes: 5 additions & 0 deletions test/stringify.js
Expand Up @@ -18,6 +18,11 @@ test('stringify()', function (t) {
st.end();
});

t.test('adds query prefix', function (st) {
st.equal(qs.stringify({ a: 'b' }, { addQueryPrefix: true }), '?a=b');
st.end();
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, regarding the new addQueryPrefix option, which is wonderful news, I noticed the following situation:

> qs.stringify({ a: 1, b: 2}, { addQueryPrefix: true })
'?a=1&b=2'
> qs.stringify({}, { addQueryPrefix: true})
'?'

In my use case I don't want to keep the lonely ? if I'm stringifying an empty object.

What do you think about it?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That seems like a reasonable modification - I haven't released the feature yet, so can you get a PR up asap for that?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in #217, thanks!


t.test('stringifies a nested object', function (st) {
st.equal(qs.stringify({ a: { b: 'c' } }), 'a%5Bb%5D=c');
st.equal(qs.stringify({ a: { b: { c: { d: 'e' } } } }), 'a%5Bb%5D%5Bc%5D%5Bd%5D=e');
Expand Down