オブジェクトをURLクエリパラメータのリストにシリアル化する方法は?


148

JavaScriptのキーを知らずにObject、どうすれば次のように変換できますか...

var obj = {
   param1: 'something',
   param2: 'somethingelse',
   param3: 'another'
}

obj[param4] = 'yetanother';

...に...

var str = 'param1=something&param2=somethingelse&param3=another&param4=yetanother';

...?


再帰的な解決策を探していますか?
Jared Farrish 2011

1
@Jared私は再帰的な解決策:)を追加
アレックス

@alex-ありがとうございます。より複雑な問題について、経験豊富な人々からの回答を見るのが好きです。:)
Jared Farrish 2011

2
@Jaredご存知のように、私は自分が経験豊富な JavaScript開発者だとは思っていません。それがうまくいくまでハックのように:)
alex

@alex-そうそう、私も。しかし、私がそれに取り組もうとしていた方法と比較して、あなたがまとめたものはどうでしょうか?私はいつも驚いています。
Jared Farrish 2011

回答:


104
var str = "";
for (var key in obj) {
    if (str != "") {
        str += "&";
    }
    str += key + "=" + encodeURIComponent(obj[key]);
}

例:http : //jsfiddle.net/WFPen/


3
再帰を伴う関数を使用しないのはなぜですか?
Jared Farrish 2011

1
ありがとう@aroth!私は、@ patrickの回答をあなたの質問(これらは基本的に同じです)よりも受け入れたのは、彼が最初だったからだと思います。お返事ありがとうございました。
bobsoap 2011

4
@bobsoap:@arothは私よりも少し先だったと思うので、@ arothに他のすべての条件が同じであるティックを指定します。
user113716 2011

3
obj [key]はencodeURIComponent()でラップすべきではありませんか?'somethingelse'が 'something&else'だった場合はどうなりますか?
James S

1
これは受け入れられる答えではなく、このstackoverflowスレッドのほぼすべての答えになるべきではないと私は確信してます。以下の可能な@zacの回答を除いて、それらのどれもないという主な理由は、このオブジェクトを適切にエンコードすることで満たされます。@ UnLoCoが機能する{ a:[ 1, 2 ], b:{ c:3, d:[ 4, 5 ], e:{ x:[ 6 ], y:7, z:[ 8, 9 ] }, f:true, g:false, h:undefined }, i:[ 10, 11 ], j:true, k:false, l:[ undefined, 0 ], m:"cowboy hat?" };NPMライブラリを提案しているように見えます。
ウェス


120

エレガントなもの:(最新のブラウザーまたはノードを実行していると想定)

var str = Object.keys(obj).map(function(key) {
  return key + '=' + obj[key];
}).join('&');

そして、ES2017相当:(Lukasに感謝)

let str = Object.entries(obj).map(([key, val]) => `${key}=${val}`).join('&');

注:encodeURIComponent()キー/値がURLエンコードされていない場合に使用することをお勧めします。


50
変更するだけです+ encodeURIComponent(obj[key])
Jacob Valenta

1
@JacobValentaそれは質問の一部ではありません
benweet

5
こちらはES2015ですObject.entries(obj).map(([key, val]) => `${key}=${val}`).join('&')
Lukas

2
オブジェクトにネストされたプロパティがある場合、これは機能しません。
Sean the Bean

2
:へES2015回答チェンジエンコードするには=${encodeURIComponent(val)}
BBlackwo

49

これはどう?これは1行で依存関係はありません。

new URLSearchParams(obj).toString();
// OUT: param1=something&param2=somethingelse&param3=another&param4=yetanother

次のように組み込みのURLで使用します。

let obj = { param1: 'something', param2: 'somethingelse', param3: 'another' }
obj['param4'] = 'yetanother';
const url = new URL(`your_url.com`);
url.search = new URLSearchParams(obj);
const response = await fetch(url);

[2020年4月4日編集]:コメントに記載されているように、null値は文字列として解釈されます'null'。したがって、null値に注意してください。


10
これは1マイルのベストアンサーです
hraban

注:ノード<10では、インポート/要求する必要があります。例:const { URLSearchParams } = require("url");
Groovecoder

1
@HonsaStunna多次元オブジェクトをURLパラメータに配置することを考えたことはありません。通常は、POSTとJSONを使用します
jfunk

1
これとnull値に注意してください。
Xaraxia

25

ES2017のアプローチ

Object.entries(obj).map(([key, val]) => `${key}=${val}`).join('&')

1
ES2017、技術的に。
Nick Zalutskiy、2017年

1
これには、キーと値の両方のエンコードが必要です。encodeURIComponentに関する他の回答を参照してください。
hraban

24

ES6:

function params(data) {
  return Object.keys(data).map(key => `${key}=${encodeURIComponent(data[key])}`).join('&');
}

console.log(params({foo: 'bar'}));
console.log(params({foo: 'bar', baz: 'qux$'}));


19

1レベルの深さのために...

var serialiseObject = function(obj) {
    var pairs = [];
    for (var prop in obj) {
        if (!obj.hasOwnProperty(prop)) {
            continue;
        }
        pairs.push(prop + '=' + obj[prop]);
    }
    return pairs.join('&');
}

jsFiddle

任意の深さのオブジェクトに対する再帰関数についての話がありました...

var serialiseObject = function(obj) {
    var pairs = [];
    for (var prop in obj) {
        if (!obj.hasOwnProperty(prop)) {
            continue;
        }
        if (Object.prototype.toString.call(obj[prop]) == '[object Object]') {
            pairs.push(serialiseObject(obj[prop]));
            continue;
        }
        pairs.push(prop + '=' + obj[prop]);
    }
    return pairs.join('&');
}

jsFiddle

もちろん、これは入れ子のコンテキストがシリアライゼーションで失われることを意味します。

値が最初からURLエンコードされておらず、URLで使用する場合は、JavaScriptを確認してくださいencodeURIComponent()


1
alex:申し訳ありませんが、私たちは休業しています...; o)
user113716

:私はあることが喜んよりも安全であることのために1 .hasOwnProperty(prop)
user113716 2011

これは素晴らしいです-とりあえず1レベルだけ必要ですが、再帰関数は良いです。追加してくれてありがとう!
bobsoap 2011

1
@ ripper234必要に応じて、このメソッドを使用しないでください。
アレックス2013

6
Object.keys(obj).map(k => `${encodeURIComponent(k)}=${encodeURIComponent(obj[k])}`).join('&')

5

参考までに、ES6をサポートするブラウザを使用している場合の解決策を次に示しますreduce

Object.keys(obj).reduce((prev, key, i) => (
  `${prev}${i!==0?'&':''}${key}=${obj[key]}`
), '');

そして、これが実際のスニペットです!

// Just for test purposes
let obj = {param1: 12, param2: "test"};

// Actual solution
let result = Object.keys(obj).reduce((prev, key, i) => (
  `${prev}${i!==0?'&':''}${key}=${obj[key]}`
), '');

// Run the snippet to show what happens!
console.log(result);


4

私は再帰関数についてとても重要なことをしたので、これは私自身のバージョンです。

function objectParametize(obj, delimeter, q) {
    var str = new Array();
    if (!delimeter) delimeter = '&';
    for (var key in obj) {
        switch (typeof obj[key]) {
            case 'string':
            case 'number':
                str[str.length] = key + '=' + obj[key];
            break;
            case 'object':
                str[str.length] = objectParametize(obj[key], delimeter);
        }
    }
    return (q === true ? '?' : '') + str.join(delimeter);
}

http://jsfiddle.net/userdude/Kk3Lz/2/


3
いくつかのランダムな考え(a)[]new Array()(b)よりも優先されます(b)delimiter = delimiter || '&';引数のデフォルトに使用できます(そして、スペルを間違えました)(c)で反復するfor ( in )と、プロトタイプチェーン上のものを含む、列挙可能なすべてのプロパティが反復されます(obj.hasOwnProperty()これを防御します) (d)物事が何であるかについて嘘をつくtypeofことができます。たとえば、いくつかの数値はObject、コンストラクターで構築された場合Number()(e)メンバーを追加Arrayするpush()メソッドを持っている場合(f)と比較しtrueて冗長です。私はひどい野郎ですが、あなたはフィードバックを求めていました!:)
アレックス

1
...そして、もしあなたがクロックフォードがすべてについて正しいと思うなら、あなたはスイッチケースを失敗させてはいけません。私はそれについて彼に同意しません。:D
アレックス

@alex-ありがたいです。a)最初はそれがあり、遅くて眠かった。b)改善点がわからない場合、2つ目も睡眠不足の瞬間でした。c)なぜ使用したのか疑問に思いましたhasOwnProperty()。d)それは確かに真実であり、良い点です。e)push()またはの使用pop()方法に慣れたことがない。f)するbreakかしないかbreak、それが問題です。詳しいご入力ありがとうございます。:)
Jared Farrish、2011

4

クエリに配列がある場合に役立つコード:

var queryString = Object.keys(query).map(key => {
    if (query[key].constructor === Array) {
        var theArrSerialized = ''
        for (let singleArrIndex of query[key]) {
            theArrSerialized = theArrSerialized + key + '[]=' + singleArrIndex + '&'
        }
        return theArrSerialized
    }
    else {
        return key + '=' + query[key] + '&'
    }
}
).join('');
console.log('?' + queryString)

4

NodeJS 13.1以降を使用している場合は、ネイティブクエリ文字列モジュールを使用してクエリ文字列を解析できます。

const qs = require('querystring');
let str = qs.stringify(obj)

3
var str = '';

for( var name in obj ) {
    str += (name + '=' + obj[name] + '&');
}

str = str.slice(0,-1);

これを試してみてください。

例: http : //jsfiddle.net/T2UWT/


1
@Jared:ループほど効率的ではありません。
user113716 2011

@Jared:QsおよびAsの下ではユーザー名は必要ありません。通知は自動です。
user113716 2011

「パフォーマンスが低い」?任意のオブジェクトを渡して、GET文字列を返したい場合、パフォーマンスはそれとどのように関係しますか?
Jared Farrish 2011

@Jared:すみませんが、おそらく私はあなたの意味を理解していません。ループではなく再帰関数呼び出しの使用を提案している場合、再帰関数の実行がループよりも遅くなることは確かです。あなたの言い分を誤解しましたか?
user113716 2011

1
まあ、私は推測するのかわかりません。オブジェクトを送信して、そのオブジェクトの文字列連結されたGET修飾バージョンを出力する関数があった場合、単一のループが常に入力を処理するとは思いません。もちろん、単一レベルのループは常に複数レベルの再帰を「上回ります」が、単一レベルのループは複数レベルのオブジェクトであるIMOさえ処理しません。
Jared Farrish 2011

3

jQueryのparamメソッドを使用できます。

var obj = {
  param1: 'something',
  param2: 'somethingelse',
  param3: 'another'
}
obj['param4'] = 'yetanother';
var str = jQuery.param(obj);
alert(str);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


3
new URLSearchParams({hello: 'world', foo: 'bar' }).toString()

仕事をするようです。必要はありませんencodeURIComponent。アウトプットhello=world&foo=bar


1
これは私が投稿したものに対する重複した回答です。
jfunk

2

指定されたオブジェクトに基づいて適切なURLパラメーターを生成する再帰関数が必要な場合は、Coffee-Script関数を試してください。

@toParams = (params) ->
    pairs = []
    do proc = (object=params, prefix=null) ->
      for own key, value of object
        if value instanceof Array
          for el, i in value
            proc(el, if prefix? then "#{prefix}[#{key}][]" else "#{key}[]")
        else if value instanceof Object
          if prefix?
            prefix += "[#{key}]"
          else
            prefix = key
          proc(value, prefix)
        else
          pairs.push(if prefix? then "#{prefix}[#{key}]=#{value}" else "#{key}=#{value}")
    pairs.join('&')

またはコンパイルされたJavaScript ...

toParams = function(params) {
  var pairs, proc;
  pairs = [];
  (proc = function(object, prefix) {
    var el, i, key, value, _results;
    if (object == null) object = params;
    if (prefix == null) prefix = null;
    _results = [];
    for (key in object) {
      if (!__hasProp.call(object, key)) continue;
      value = object[key];
      if (value instanceof Array) {
        _results.push((function() {
          var _len, _results2;
          _results2 = [];
          for (i = 0, _len = value.length; i < _len; i++) {
            el = value[i];
            _results2.push(proc(el, prefix != null ? "" + prefix + "[" + key + "][]" : "" + key + "[]"));
          }
          return _results2;
        })());
      } else if (value instanceof Object) {
        if (prefix != null) {
          prefix += "[" + key + "]";
        } else {
          prefix = key;
        }
        _results.push(proc(value, prefix));
      } else {
        _results.push(pairs.push(prefix != null ? "" + prefix + "[" + key + "]=" + value : "" + key + "=" + value));
      }
    }
    return _results;
  })();
  return pairs.join('&');
};

これは次のように文字列を構築します:

toParams({a: 'one', b: 'two', c: {x: 'eight', y: ['g','h','j'], z: {asdf: 'fdsa'}}})

"a=one&b=two&c[x]=eight&c[y][0]=g&c[y][1]=h&c[y][2]=j&c[y][z][asdf]=fdsa"

私はそれを壁に掛けると思います
pie6k

2

機能的なアプローチ。

var kvToParam = R.mapObjIndexed((val, key) => {
  return '&' + key + '=' + encodeURIComponent(val);
});

var objToParams = R.compose(
  R.replace(/^&/, '?'),
  R.join(''),
  R.values,
  kvToParam
);

var o = {
  username: 'sloughfeg9',
  password: 'traveller'
};

console.log(objToParams(o));
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.22.1/ramda.min.js"></script>


1
Object.toparams = function ObjecttoParams(obj) 
{
  var p = [];
  for (var key in obj) 
  {
    p.push(key + '=' + encodeURIComponent(obj[key]));
  }
  return p.join('&');
};

0

このメソッドは、再帰を使用してオブジェクト階層に降り、レールが埋め込みハッシュとして解釈するレールスタイルパラメータを生成します。objToParamsは、末尾に追加のアンパサンドを含むクエリ文字列を生成し、objToQueryは最後のアンパサンドを削除します。

 function objToQuery(obj){
  let str = objToParams(obj,'');
  return str.slice(0, str.length);
}
function   objToParams(obj, subobj){
  let str = "";

   for (let key in obj) {
     if(typeof(obj[key]) === 'object') {
       if(subobj){
         str += objToParams(obj[key], `${subobj}[${key}]`);
       } else {
         str += objToParams(obj[key], `[${key}]`);
       }

     } else {
       if(subobj){
         str += `${key}${subobj}=${obj[key]}&`;
       }else{
         str += `${key}=${obj[key]}&`;
       }
     }
   }
   return str;
 }

0

npm lib query-stringを使用できます

const queryString = require('query-string');

querystring.stringify({ foo: 'bar', baz: ['qux', 'quux'], corge: '' });
// Returns 'foo=bar&baz=qux&baz=quux&corge='

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.