Skip to content

Instantly share code, notes, and snippets.

@kaichen
Created February 5, 2011 08:11
Show Gist options
  • Select an option

  • Save kaichen/812309 to your computer and use it in GitHub Desktop.

Select an option

Save kaichen/812309 to your computer and use it in GitHub Desktop.
#!/usr/bin/env coffee
queryString = require('querystring')
util = require("util")
parser = module.exports = (qs, sep, eq) ->
sep = sep || '&'
eq = eq || '='
params = {}
if (typeof qs != 'string' || qs.length == 0)
return obj
qs.split('&').forEach (kvp) ->
return if kvp == ""
x = kvp.split("=")
k = queryString.unescape(x[0], true)
v = queryString.unescape(x.slice(1).join("="), true)
v = undefined if v == "" && x.length == 1
normalizeParams(params, k, v)
params
normalizeParams = (params, name, value) ->
sliced = /^\[?([^\[\]]+)\]?/.exec(name)
if sliced and sliced[1]
key = sliced[1]
else
key = ""
after = name.slice(sliced[0].length)
return if key == ""
if after == ""
params[key] = value
else if after == "[]"
params[key] ?= []
params[key].push(value)
else if /^\[\](.+)$/.test(after)
fragments = /^\[\]\[([^\[\]]+)\]/.exec(after)
childKey = fragments[1] + after.slice(fragments[0].length)
params[key] ?= []
lastParams = params[key][params[key].length - 1]
if params[key].length == 0 || lastParams[childKey]
params[key].push normalizeParams({}, childKey, value)
else
lastParams = normalizeParams(lastParams, childKey, value)
else
params[key] ?= {}
params[key] = normalizeParams(params[key], after, value)
params
# vim:set sts=2 sw=2:
#!/usr/bin/env coffee
vows = require("vows")
assert = require("assert")
equiv = require("./equiv")
util = require("util")
parser = require("./parser").parseNested
assert.equiv = (expected, actual, message) ->
if !equiv(actual, expected)
message ?= "expected {expected},\nbut got {actual}"
assert.fail(util.inspect(expected, false, 9),
util.inspect(actual, false, 9),
message, 'equiv', assert.equiv)
assertFn = assert.equiv
vows.describe("Nested query strings").addBatch
"A context":
tipic: true,
"test parse normal query strings" : (topic) ->
assertFn(parser("foo"), {"foo":""})
assertFn(parser("foo="), {"foo":""})
assertFn(parser("foo=bar"), {"foo":"bar"})
assertFn(parser("foo=\"bar\""), {"foo":"\"bar\""})
assertFn(parser("foo=bar&foo=quux"), {"foo":"quux"})
assertFn(parser("foo&foo=quux"), {"foo":"quux"})
assertFn(parser("foo=1&bar=2"), {"foo":"1","bar":"2"})
assertFn(parser("&foo=1&&bar=2"), {"foo":"1","bar":"2"})
assertFn(parser("foo&bar="), {"foo":"","bar":""})
assertFn(parser("foo=bar&baz="), {"foo":"bar","baz":''})
"test parse array like query strings" : (topic) ->
assertFn(parser("foo[]"), {"foo":[""]})
assertFn(parser("foo[]="), {"foo":[""]})
assertFn(parser("foo[]=bar"), {"foo":["bar"]})
assertFn(parser("foo[]=1&foo[]=2"), {"foo":["1","2"]})
assertFn(parser("foo=bar&baz[]=1&baz[]=2&baz[]=3"),
{"foo":"bar", "baz":["1", "2", "3"]})
assertFn(parser("foo[]=bar&baz[]=1&baz[]=2&baz[]=3"),
{"foo":["bar"], "baz":["1", "2", "3"]})
"test parse hash like query strings" : (topic) ->
assertFn(parser("x[y][z]=1"), {"x":{"y":{"z":"1"}}})
assertFn(parser("x[y][z][]=1"), {"x":{"y":{"z":["1"]}}})
assertFn(parser("x[y][z]=1&x[y][z]=2"), {"x":{"y":{"z":"2"}}})
assertFn(parser("x[y][z][]=1&x[y][z][]=2"),
{"x":{"y":{"z":["1","2"]}}})
assertFn(parser("x[y][][z]=1"), {"x":{"y":[{"z":"1"}]}})
assertFn(parser("x[y][][z][]=1"), {"x":{"y":[{"z":["1"]}]}})
assertFn(parser("x[y][][z]=1&x[y][][w]=2"),
{"x":{"y":[{"z":"1","w":"2"}]}})
assertFn(parser("x[y][][v][w]=1"), {"x":{"y":[{"v":{"w":"1"}}]}})
assertFn(parser("x[y][][z]=1&x[y][][v][w]=2"),
{"x":{"y":[{"z":"1", "v":{"w":"2"}}]}})
assertFn(parser("x[y][][z]=1&x[y][][z]=2"),
{"x":{"y":[{"z":"1"},{"z":"2"}]}})
assertFn(parser("x[y][][z]=1&x[y][][w]=a&x[y][][z]=2&x[y][][w]=3"),
{"x":{"y":[{"z":"1","w":"a"},{"z":"2","w":"3"}]}})
.export(module)
# vim:set sts=2 sw=2:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment