Comparing version 0.1.0 to 0.2.0
@@ -5,2 +5,5 @@ (function(){ | ||
dotQs = { | ||
options : { | ||
arrayStyle : 'DOT', // DOT | BRANCKET | ||
} | ||
}; | ||
@@ -65,2 +68,4 @@ | ||
var notint = /[^0-9]/; | ||
var brancketSeparator = /\.|\[(\d+)\]/; | ||
var initialBrancket = /^\[(\d+)\]/; | ||
dotQs.parse = function(str){ | ||
@@ -88,11 +93,27 @@ if(str === null || str === ''){ | ||
var store = function(key, base){ | ||
var dpos = key.indexOf('.'); | ||
var baseKey, remainKey; | ||
if(dpos == -1){ | ||
var brancketMatch | ||
if(dotQs.options.arrayStyle === 'BRANCKET' && (brancketMatch = key.match(initialBrancket))){ | ||
baseKey = brancketMatch[1]; | ||
remainKey = key.substring(brancketMatch[0].length); | ||
}else{ | ||
var spos; | ||
if(dotQs.options.arrayStyle === 'BRANCKET'){ | ||
spos = key.search(brancketSeparator); | ||
}else{ | ||
spos = key.indexOf('.'); | ||
} | ||
if(spos == -1){ | ||
baseKey = key; | ||
remainKey = null; | ||
}else{ | ||
baseKey = key.substring(0, dpos); | ||
remainKey = key.substring(dpos + 1); | ||
baseKey = key.substring(0, spos); | ||
remainKey = key.substring(spos); | ||
} | ||
} | ||
if(remainKey && remainKey[0] === '.'){ | ||
remainKey = remainKey.substring(1); | ||
} | ||
@@ -108,3 +129,3 @@ // store object | ||
base = base || []; | ||
if(remainKey == null){ | ||
if(remainKey === null || remainKey === ''){ | ||
if(value === ''){ | ||
@@ -126,3 +147,3 @@ base[index] = null; | ||
base = base || {}; | ||
if(remainKey == null){ | ||
if(remainKey === null || remainKey === ''){ | ||
if(value === ''){ | ||
@@ -149,41 +170,40 @@ base[baseKey] = null; | ||
var slot = []; | ||
var updateSlot = function(obj){ | ||
var ret = {}; | ||
var _dump = function(obj, prefix, parents){ | ||
var checkedParents = []; | ||
if(parents){ | ||
var i; | ||
for(i = 0; i < slot.length; i++){ | ||
if(slot[i] === obj){ | ||
return false; | ||
for(i = 0; i < parents.length; i++){ | ||
if(parents[i] === obj){ | ||
throw new Error('object has circular references'); | ||
} | ||
checkedParents.push(obj); | ||
} | ||
slot.push(obj); | ||
return true; | ||
}; | ||
var ret = {}; | ||
var _dump = function(obj, prefix){ | ||
if(!isArray(obj) && !isObject(obj) ){ | ||
if(!prefix){ | ||
throw obj + "is not object or array"; | ||
} | ||
ret[prefix] = obj; | ||
return; | ||
} | ||
checkedParents.push(obj); | ||
if(!isArray(obj) && !isObject(obj) ){ | ||
if(!prefix){ | ||
throw obj + "is not object or array"; | ||
} | ||
ret[prefix] = obj; | ||
return; | ||
} | ||
if(isArray(obj)){ | ||
// it's array | ||
_forEach(obj, function(obj, i){ | ||
if(!updateSlot(obj)){ | ||
throw new Error('object has circular references'); | ||
} | ||
_dump(obj, prefix ? prefix + "." + i : "" + i); | ||
}); | ||
}else{ | ||
// it's object | ||
_forEach(obj, function(obj, key){ | ||
if(!updateSlot(obj)){ | ||
throw new Error('object has circular references'); | ||
} | ||
_dump(obj, prefix ? prefix + "." + key : "" + key); | ||
}); | ||
} | ||
}; | ||
if(isArray(obj)){ | ||
// it's an array | ||
_forEach(obj, function(obj, i){ | ||
if(dotQs.options.arrayStyle === 'BRANCKET'){ | ||
_dump(obj, (prefix || "") + "[" + i + "]", checkedParents); | ||
}else{ | ||
_dump(obj, prefix ? prefix + "." + i : "" + i, checkedParents); | ||
} | ||
}); | ||
}else{ | ||
// it's an object | ||
_forEach(obj, function(obj, key){ | ||
_dump(obj, prefix ? prefix + "." + key : "" + key, checkedParents); | ||
}); | ||
} | ||
}; | ||
@@ -190,0 +210,0 @@ _dump(obj, null); |
{ | ||
"name": "dot-qs", | ||
"version": "0.1.0", | ||
"version": "0.2.0", | ||
"description": "Dot separated format version of node-querystring", | ||
@@ -16,2 +16,2 @@ "keywords": [], | ||
"engines": { "node": "*" } | ||
} | ||
} |
@@ -5,7 +5,19 @@ # dot-querystring | ||
## Examples | ||
## Install | ||
``` | ||
npm install dot-qs | ||
``` | ||
## Examples | ||
### stringify / parse | ||
```js | ||
// set array style to using dot (default). | ||
dotQs.options = { | ||
arrayStyle : 'DOT' | ||
}; | ||
dotQs.stringify({a :{ b : 2}}) | ||
@@ -22,2 +34,20 @@ // -> 'a.b=2' | ||
// -> { a: [ 'hoge', 'fuga' ] } | ||
// set array style to using brancket | ||
dotQs.options = { | ||
arrayStyle : 'BRANCKET' | ||
}; | ||
dotQs.stringify({a :{ b : 2}}) | ||
// -> 'a.b=2' | ||
dotQs.stringify({a :[1,2,3,4,5]}) | ||
// -> '"a%5B0%5D=1&a%5B1%5D=2&a%5B2%5D=3&a%5B3%5D=4&a%5B4%5D=5"' | ||
dotQs.parse('a.b.c=1&a.b.d=2') | ||
// -> { a: { b: { c: '1', d: '2' } } } | ||
dotQs.parse('a[0]=hoge&a[1]=fuga') | ||
// -> { a: [ 'hoge', 'fuga' ] } | ||
``` | ||
@@ -28,2 +58,7 @@ | ||
```js | ||
// set array style to using dot (default). | ||
dotQs.options = { | ||
arrayStyle : 'DOT' | ||
}; | ||
dotQs.flatten({name : 'john', emails : ['john@example.com', 'john2@example.com']}) | ||
@@ -33,4 +68,36 @@ // -> { name: 'john', | ||
// 'emails.1': 'john2@example.com' } | ||
// set array style to using brancket | ||
dotQs.options = { | ||
arrayStyle : 'BRANCKET' | ||
}; | ||
dotQs.flatten({name : 'john', emails : ['john@example.com', 'john2@example.com']}) | ||
// -> { name: 'john', | ||
// 'emails[0]': 'john@example.com', | ||
// 'emails[1]': 'john2@example.com' } | ||
``` | ||
## Browser support | ||
Copy lib/dot-querystring.js to your project. | ||
``` | ||
<script type="text/javascript" src="dot-querystring.js"></script> | ||
<!-- optional --> | ||
<script type="text/javascript" src="jQuery.js"></script> | ||
<script type="text/javascript"> | ||
// use with jQuery.ajax | ||
var obj = {name : 'john', emails : ['john@example.com', 'john2@example.com']}; | ||
// this will access http://example.com/foo?name=john&emails.0=john%40example.com&emails.1=john2%40example.com | ||
$.ajax({ | ||
url : 'http://example.com/foo', | ||
data : dotQs.flatten(obj) | ||
}); | ||
</script> | ||
``` | ||
## License | ||
@@ -37,0 +104,0 @@ |
@@ -6,2 +6,8 @@ if(typeof dotQs === 'undefined'){ | ||
describe('dotQs.parse', function(){ | ||
beforeEach(function(done){ | ||
dotQs.options = { | ||
arrayStyle : 'DOT' | ||
}; | ||
done(); | ||
}); | ||
it('shold ignore left-hand only', function(){ | ||
@@ -11,2 +17,6 @@ dotQs.parse('aaa').should.eql({}); | ||
it('shold care blank value', function(){ | ||
dotQs.parse('aaa=').should.eql({'aaa' : null}); | ||
}); | ||
it('shold parse object', function(){ | ||
@@ -43,3 +53,39 @@ dotQs.parse('aaa=bbb').should.eql({'aaa' : 'bbb'}); | ||
describe('dotQs.parse (bracket style array)', function(){ | ||
beforeEach(function(done){ | ||
dotQs.options = { | ||
arrayStyle : 'BRANCKET' | ||
}; | ||
done(); | ||
}); | ||
it('shold parse array', function(){ | ||
dotQs.parse('[0]=bbb&[1]=ccc').should.eql(['bbb', 'ccc']); | ||
}); | ||
it('shold use type of appeared first', function(){ | ||
dotQs.parse('[0]=1&a=2').should.eql(['1']); | ||
dotQs.parse('a=2&[0]=1').should.eql({a : '2'}); | ||
}); | ||
it('should skip empty array indexes', function(){ | ||
dotQs.parse('[3]=3').should.eql([,,,'3']); | ||
}); | ||
it('should parse nested', function(){ | ||
dotQs.parse('a.b.c=1&a.b.d=2').should.eql({a : {b : {c : '1', d : '2'}}}); | ||
dotQs.parse('a[0].a=1&a[0].b=2&a[1].a=3&a[1].b=4').should.eql({a : [{a : '1', b : '2'}, {'a' : '3', 'b' : '4'}]}); | ||
dotQs.parse('a[0][0]=test1&a[0][1]=test2').should.eql({a : [['test1' , 'test2']]}); | ||
}); | ||
}); | ||
describe('dotQs.flatten', function(){ | ||
beforeEach(function(done){ | ||
dotQs.options = { | ||
arrayStyle : 'DOT' | ||
}; | ||
done(); | ||
}); | ||
it('should flatten object', function(){ | ||
@@ -83,3 +129,66 @@ dotQs.flatten({a : {b : 1, c : 2}}).should.eql({'a.b' : 1, 'a.c' : 2}); | ||
describe('dotQs.flatten (bracket style array)', function(){ | ||
beforeEach(function(done){ | ||
dotQs.options = { | ||
arrayStyle : 'BRANCKET' | ||
}; | ||
done(); | ||
}); | ||
it('should flatten object', function(){ | ||
dotQs.flatten({a : {b : 1, c : 2}}).should.eql({'a.b' : 1, 'a.c' : 2}); | ||
}); | ||
it('should flatten array', function(){ | ||
dotQs.flatten([1,2,3]).should.eql({'[0]' : 1, '[1]' : 2, '[2]' : 3}); | ||
}); | ||
it('should flatten nested', function(){ | ||
dotQs.flatten({ | ||
a : 12345, | ||
b : { | ||
c : 'hoge', | ||
d : ['a', 'b'] | ||
} | ||
}).should.eql({ | ||
'a' : 12345, | ||
'b.c' : 'hoge', | ||
'b.d[0]' : 'a', | ||
'b.d[1]' : 'b' | ||
}); | ||
dotQs.flatten( | ||
[[1,2,3], [4,[5]]] | ||
).should.eql({ | ||
'[0][0]' : 1, | ||
'[0][1]' : 2, | ||
'[0][2]' : 3, | ||
'[1][0]' : 4, | ||
'[1][1][0]' : 5 | ||
}); | ||
}); | ||
it('should detect circular references', function(){ | ||
(function(){ | ||
var foo = {a : 1 }; | ||
foo.foo = foo; | ||
dotQs.flatten(foo); | ||
}).should.throw(); | ||
(function(){ | ||
var foo = {a : 1, b : [1,2,3]}; | ||
foo.b.push(foo); | ||
dotQs.flatten(foo); | ||
}).should.throw(); | ||
}); | ||
}); | ||
describe('dotQs.stringify', function(){ | ||
beforeEach(function(done){ | ||
dotQs.options = { | ||
arrayStyle : 'DOT' | ||
}; | ||
done(); | ||
}); | ||
it('should stringify basic objects', function(){ | ||
@@ -105,2 +214,32 @@ dotQs.stringify({a : 1}).should.eql('a=1'); | ||
}); | ||
}); | ||
describe('dotQs.stringify (bracket style array)', function(){ | ||
beforeEach(function(done){ | ||
dotQs.options = { | ||
arrayStyle : 'BRANCKET' | ||
}; | ||
done(); | ||
}); | ||
it('should stringify basic objects', function(){ | ||
dotQs.stringify({a : 1}).should.eql('a=1'); | ||
dotQs.stringify({a : 'あ'}).should.eql('a=%E3%81%82'); | ||
}); | ||
it('should stringify basic array', function(){ | ||
dotQs.stringify([1,2,3,4,5]).should.eql('%5B0%5D=1&%5B1%5D=2&%5B2%5D=3&%5B3%5D=4&%5B4%5D=5'); | ||
dotQs.stringify(['あ','い']).should.eql('%5B0%5D=%E3%81%82&%5B1%5D=%E3%81%84'); | ||
}); | ||
it('should stringify nested object', function(){ | ||
dotQs.stringify({ | ||
a : 12345, | ||
b : { | ||
c : 'hoge', | ||
d : ['a', 'b'], | ||
'あいうえお' : 3 | ||
} | ||
}).should.eql('a=12345&b.c=hoge&b.d%5B0%5D=a&b.d%5B1%5D=b&b.%E3%81%82%E3%81%84%E3%81%86%E3%81%88%E3%81%8A=3'); | ||
}); | ||
}); |
141220
5390
109