URLを解析するQsを丁寧に説明してみた
Qsって何?
クエリの解析,文字列化をするライブラリです.
使っていて非常に便利なので一旦まとめようと思います.
基本的な使い方
import qs from 'qs'; // (以下省略)
const obj = qs.parse('a=c'); // { a: 'c' }
const str = qs.stringify(obj); // 'a=c'
簡単に言うと,parse
はURLなどの文字列をオブジェクトに変換するメソッドで, stringify
はオブジェクトをURL形式の文字列に変換するメソッドです.
またqsはネストしたオブジェクトも生成することができます.
例えば'foo[bar]=baz'
は
foo: {
bar: 'baz'
}
を生成します.
このように[]
を使ってサブキーを作成することができます.
Parseについて
オブションパラメータ
qsはいくつかオプションパラメータをとることができます.
- plainObjects
const nullObject = qs.parse('a[hasOwnProperty]=b', { plainObjects: true });
このようにするとObject.create(null)
で生成されたオブジェクトとして返されます.つまりプロトタイプメソッドが使えません.
- allowPrototypes
const protoObject = qs.parse('a[hasOwnProperty]=b', { allowPrototypes: true });
これはプロトタイプのプロパティを変更することができますが,使用時に問題が起きることがあり,推奨されていません.
-
ignoreQueryPrefix
このオプションをつけることでクエスチョンマークから始まる文字列も解析することができます.
const nomal = qs.parse('?a=b&c=d'); // { ?a: "b", c: "d" }
const prefixed = qs.parse('?a=b&c=d', { ignoreQueryPrefix: true }); // {a: "b", c: "d"}
-
delimiter
このオプションをつけることで区切りもじを考えずに解析することができます.
const delimited = qs.parse('a=b;c=d', { delimiter: ';' }); // { a: 'b', c: 'd' }
const regexed = qs.parse('a=b;c=d,e=f', { delimiter: /[;,]/ }); // { a: 'b', c: 'd', e: 'f' }
-
allowDots
このオプションをつけることでドットのオブジェクト表記を解析することができます.
const withDots = qs.parse('a.b=c', { allowDots: true }); // { a: { b: 'c' } }
こんなのもできる
-
URL encodeされた文字列の解析
qsはURL encodedされた文字列もきちんとオブジェクトにすることができます.
const urlEncoded = qs.parse('a%5Bb%5D=c'); // a: { b: "c" }
-
ネストされた文字列の解析
ネストしたような構造も正しく解析することができます.
const nested = qs.parse('foo[bar][baz]=foobarbaz');
/**
{
foo: {
bar: {
baz: 'foobarbaz'
}
}
}
*/
-
ネストする深さを設定できる
上記ではネストの深さは5つの子までと説明しましたが,オプションで変更できます.
const deep = qs.parse('a[b][c][d][e][f][g][h][i]=j', { depth: 1 });
-
解析するパラメータの上限を設定できる
qsはデフォルトでは1000つのパラメータしか解析しません.ですがparameterLimit
というオプションを使って解析するパラメータ数を制限することができます.
const limited = qs.parse('a=b&c=d', { parameterLimit: 1 }); // { a: 'b' }
配列型の解析
qsは配列型の文字列も解析できます.
例を見た方が分かりやすいと思います.
const withArray = qs.parse('a[]=b&a[]=c'); // { a: ['b', 'c'] }
インデックスをつけたものも解析できます.
const withIndexes = qs.parse('a[1]=c&a[0]=b'); // { a: ['b', 'c'] }
記号を混ぜるとオブジェクトとしてまとめられます.
const mixedNotation = qs.parse('a[0]=b&a[b]=c'); // { a: { '0': 'b', b: 'c' }
オブジェクトの配列も作成できます.
const arraysOfObjects = qs.parse('a[][b]=c'); // { a: [{ b: 'c' }] }
コンマで結合された配列も解析することができます.
const arraysOfObjects = qs.parse('a=b,c', { comma: true }); // { a: ['b', 'c'] }
-
空文字列の扱い
空文字列も値として認識されます.
const withEmptyString = qs.parse('a[]=&a[]=b'); // { a: ['', 'b'] }
-
allowSparse
このオプションは配列のインデックスをそのまま反映するかを表します.
const noSparse = qs.parse('a[1]=b&a[15]=c'); // { a: ['b', 'c'] }
const sparseArray = qs.parse('a[1]=2&a[3]=5', { allowSparse: true }); // { a: [, '2', , '5'] }
-
arrayLimit
このオプションは配列のインデックスの制限を設定するものです.デフォルトでは20に設定されており,それより大きなインデックスを指定した場合は,代わりにその数字をキーとするオブジェクトになります.
const withArrayLimit = qs.parse('a[1]=b', { arrayLimit: 0 }); // { a: { '1': 'b' } }
-
parseArrays
このオプションは配列の解析を完全に無効にするためのものです.
const noParsingArrays = qs.parse('a[]=b', { parseArrays: false }); // { a: { '0': 'b' } }
Stringifyについて
stringifyはオブジェクトなどをURLエンコードする際に使用できます.
基本的にはparseで見てきたような雰囲気で考えて貰えば大丈夫です.
const ex = qs.stringify({ a: 'b' }); // 'a=b'
const ex2 = qs.stringify({ a: { b: 'c' } }); // 'a%5Bb%5D=c'
空文字やnull
は省略されますが,=
は残ります.
const ex = qs.stringify({ a: '' }); // 'a='
しかしundefined
は全て省略されます.
const ex = qs.stringify({ a: null, b: undefined }); // 'a='
オプション
- encode
encode
オプションをfalse
にするとエンコードを行いません.
const unencoded = qs.stringify({ a: { b: 'c' } }, { encode: false }); // 'a[b]=c'
- indices
配列を渡したときはデフォルトではインデックスが付与されますが,indices
をfalse
にして使うこともできます.
const ex = qs.stringify({ a: ['b', 'c', 'd'] }, { indices: false }); // 'a=b&a=c&a=d'
-
addQueryPrefix
このオプションを指定すると先頭にクエスチョンマークをつけて出力してくれます.
const ex = qs.stringify({ a: 'b', c: 'd' }, { addQueryPrefix: true }); // '?a=b&c=d'
- arrayFormat
arrayFormat
オプションを指定することでアウトプットを変えることができます.
qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'indices' })
// 'a[0]=b&a[1]=c'
qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'brackets' })
// 'a[]=b&a[]=c'
qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'repeat' })
// 'a=b&a=c'
qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'comma' })
// 'a=b,c'
-
delimiter
このオプションをつけることで区切りを指定できます.
const ex = qs.stringify({ a: 'b', c: 'd' }, { delimiter: ';' }
-
sort
sort
オプションによりパラメータをソートすることができます.
const ex = qs.stringify({ a: 'c', z: 'y', b : 'f' }, { sort: alphabeticalSort } // 'a=c&b=f&z=y'
nullの扱いについて
先ほども説明しましたがstringify
するとき,空文字やnull
の場合は値が省略されます.
const withNull = qs.stringify({ a: null, b: '' });
// 'a=&b='
parse
の場合は=
があってもなくても値がなければ空文字に変換されます.
const equalsInsensitive = qs.parse('a&b=');
// { a: '', b: '' }
-
strictNullHandling
このオプションを使用するとnull
の場合に=
を省略できます.
const strictNull = qs.stringify({ a: null, b: '' }, { strictNullHandling: true });
// 'a&b='
-
skipNulls
null
の値を全く表示させたくない時に使用できます.
const nullsSkipped = qs.stringify({ a: 'b', c: null}, { skipNulls: true });
// 'a=b'
終わりに
間違い等ありましたらコメントで教えていただけると嬉しいです.
Discussion