JavaScriptでクエリ文字列を作成する方法


167

フォームを受け取ってクエリパラメータを返すJavascriptに組み込みのものがあるかどうか疑問に思っています。例: "var1=value&var2=value2&arr[]=foo&arr[]=bar..."

私はこれを何年もの間考えていました。



回答:


-24

しばらく前にこの質問の答えを検索しようとしましたが、フォームから値を抽出する独自の関数を作成してしまいました。

それは完璧ではありませんが、私のニーズに合います。

function form_params( form )
{
    var params = new Array()
    var length = form.elements.length
    for( var i = 0; i < length; i++ )
    {
        element = form.elements[i]

        if(element.tagName == 'TEXTAREA' )
        {
            params[element.name] = element.value
        }
        else if( element.tagName == 'INPUT' )
        {
            if( element.type == 'text' || element.type == 'hidden' || element.type == 'password')
            {
                params[element.name] = element.value
            }
            else if( element.type == 'radio' && element.checked )
            {
                if( !element.value )
                    params[element.name] = "on"
                else
                    params[element.name] = element.value

            }
            else if( element.type == 'checkbox' && element.checked )
            {
                if( !element.value )
                    params[element.name] = "on"
                else
                    params[element.name] = element.value
            }
        }
    }
    return params;
}

form_paramsは、パラメータの(キー->値)マッピングを返します。入力はフォーム要素(DOM要素)です

複数選択が可能なフィールドは処理しません。


44
それは私だけですか、それとも質問にまったく答えませんか?彼は、マップされた配列ではなく、クエリ文字列を求めていました。
ジェイクウィルソン

2
@JakeWilsonええ、この答えは質問に半分だけ答えます。配列はまだクエリ文字列形式に入る必要があります。
ハッチムーア

8
ああ、私はJSの初心者だったに違いありません。new Array()辞書の初期化に使用します。しかし、繰り返しになりますが、コードは私が最近書いているがらくたのいくつかよりもずっときれいに見えます!
Hasen

2
@hasen多分あなたはこの答えを編集することを検討するでしょう、あるいは、ええと、まあ、それを削除しますか?スクロールするたびに投票数がどんどん増えます= -D(正の比率だったときのことも覚えています...)
Klesun

1
@ArturKlesunいや、いや。私は気にしません。質問をした人に、この回答を受け入れないように依頼してみてください。
HASEN

220

2k20の更新:URLSearchParams.toString()Joshのソリューションを使用します。

古い答え:


jQueryなし

var params = {
    parameter1: 'value_1',
    parameter2: 'value 2',
    parameter3: 'value&3' 
};

var esc = encodeURIComponent;
var query = Object.keys(params)
    .map(k => esc(k) + '=' + esc(params[k]))
    .join('&');

ES5を必要とするアロー関数構文をサポートしていないブラウザの場合は、.map...行を

    .map(function(k) {return esc(k) + '=' + esc(params[k]);})

8
私が今まで見た中で最高の解決策-とても簡潔で簡潔。ただし、いくつかの注意点があります。1).map()では、kとparams [k]の両方をエンコードする必要があります(encodeURIComponent(k)やencodeURIComponent(params [k]など)。2)クエリ文字列に名前付きパラメーターの複数のインスタンスを含めることができます。その機能が必要な場合は、オブジェクトの代わりに配列を使用する必要があります(ほとんどのアプリケーションでは、それを必要としないか、必要としません)。
John Deighan 16年

9
3)すべてのブラウザーがアロー関数構文をサポートするわけではありません(ES5が必要です)。すべてのブラウザーをサポートする(およびパーツをエンコードする)場合は、上記の.map()を.map(function(k){return encodeURIComponent(k)+ '=' + encodeURIComponent(params [k]);})に置き換えます。
John Deighan 16年

1
綺麗な。本当に美しい。
Mikko Ohtamaa 2017年

9
「jqueryが不足しています」
Eugene Pankov

1
@ user1738579回答を編集して、ES5以外の例も含めました。
テイラーエドミストン

134

jQueryを使用している場合は、http://api.jquery.com/jQuery.param/をチェックしてjQuery.param() ください。

例:

var params = {
    parameter1: 'value1',
    parameter2: 'value2',
    parameter3: 'value3' 
};
var query = $.param(params);
document.write(query);

13
これが正解です。フォームのクエリ文字列は$.param($('#myform').serializeArray())です。
Jesse

7
:@Jesseは、それは同じ結果になります$('#myform').serialize()
包丁

94
jQuery !== JavaScript
gphilip 2014

14
@gphilipさて、「jQueryを使用している場合...」で応答を開始したのはそのためです。それ以外の場合、それをバニラJSで実装する場合は、jQuery.param()ここでgithub.com/jquery/jquery/blob/master/src/serialize.jsの実装を調べることができます:)
KlemenTušarOct

2
私の回答とは異なり、これは次のようなネストされたオブジェクトをサポートしますsomeStr=value1&someObj[a]=5&someObj[b]=6&someArr[]=1&someArr[]=2
Klesun

113

URLSearchParams APIは、最新のすべてのブラウザで使用できます。例えば:

const params = new URLSearchParams({
  var1: "value",
  var2: "value2",
  arr: "foo",
});
console.log(params.toString());
//Prints "var1=value&var2=value2&arr=foo"


3
ここで最高の答えはイモです。追加するだけで、params.append(key, value)後で、より複雑なシナリオで新しい検索パラメーターを追加できます。
Mingwei Zhang

4
未定義とnull値を最終的な文字列に含まれていることに注意してくださいx=null&y=undefined
pomber

2
また、URLオブジェクト(などconst url = new URL("https://stackoverflow.com"))が既にある場合は、そのクエリ文字列を設定するurl.search = new URLSearchParams({foo: "bar"})か、url.searchParams.append("foo", "bar")
Miguel Pynto

TSはプレーンオブジェクトの使用について警告しますが、それでも問題なく機能することに注意してください
Vadorequest

@pomberこれらの未定義のアイテムを除外する上で何か良いアイデアはありますか?
ダンゲイル

53

これはあなたの質問に直接答えるものではありませんが、クエリ文字列パラメーターを含むURLを作成する一般的な関数があります。パラメータ(名前と値)は、URLに含めるために安全にエスケープされます。

function buildUrl(url, parameters){
  var qs = "";
  for(var key in parameters) {
    var value = parameters[key];
    qs += encodeURIComponent(key) + "=" + encodeURIComponent(value) + "&";
  }
  if (qs.length > 0){
    qs = qs.substring(0, qs.length-1); //chop off last "&"
    url = url + "?" + qs;
  }
  return url;
}

// example:
var url = "http://example.com/";

var parameters = {
  name: "George Washington",
  dob: "17320222"
};

console.log(buildUrl(url, parameters));
// => http://www.example.com/?name=George%20Washington&dob=17320222

1
jquery、mootoolsなどの人気のあるJavaScriptフレームワークの1つにこれに似た組み込み関数はありますか?
Samuel、

より堅牢なネイティブJavaScriptソリューションは、stackoverflow.com
a / 1714899/1269037にあります

これまでで最も奇妙な実装ですが、new Array実際にそれをオブジェクトとして使用しているときに、なぜ初期化する必要があるのですか?o、O
Umut Sirin

@UmutSirin Lolええ、私は当時、Javascriptについてよく知りませんでした。xD私はそれをPHP配列のように扱っていたと思います。必要に応じて、自由にリファクタリングしてください。
マイケル

@Michael Haha、ええ。編集を送信しました。答えてくれてありがとう!
Umut Sirin

22

jQueryを使用すると、これを行うことができます $.param

$.param({ action: 'ship', order_id: 123, fees: ['f1', 'f2'], 'label': 'a demo' })

// -> "action=ship&order_id=123&fees%5B%5D=f1&fees%5B%5D=f2&label=a+demo"

17

ES2017(ES8)

Object.entries()オブジェクトの[key, value]ペアの配列を返すを使用します。たとえば、{a: 1, b: 2}それはを返し[['a', 1], ['b', 2]]ます。IEだけではサポートされていません(サポートされません)。

コード:

const buildURLQuery = obj =>
      Object.entries(obj)
            .map(pair => pair.map(encodeURIComponent).join('='))
            .join('&');

例:

buildURLQuery({name: 'John', gender: 'male'});

結果:

"name=John&gender=male"

代わりにurl.spec.whatwg.org/#urlsearchparamsを使用してください
Boris

10

いいえ、私は標準のJavaScriptを内蔵することを持っていますが、プロトタイプJSが(確かに他のほとんどのJSのフレームワークがあまりにもありますが、私はそれらを知らない)という機能を持って、彼らはそれを呼び出すとは思わないシリアライズ

Prototype JSをお勧めします。これで問題なく動作します。私が実際に気付いた唯一の欠点は、サイズ(数百kb)とスコープ(ajax、domなどのコードがたくさん)であることです。したがって、フォームシリアライザーのみが必要な場合はやりすぎです。厳密に言えば、Ajax機能だけが必要な場合(これは主に私が使用したものです)はやりすぎです。注意していない限り、極端な場合に「マジック」(Prototype JS関数で操作するすべてのdom要素を拡張して要素を見つけるだけ)が遅くなりすぎて遅くなることがあります。


何が組み込まれているのか疑問に思います。あるように見える。私はプロトタイプが嫌いですが、私はあなたに対してそれを保持していません:)

JavaScriptが設計されたとき、Ajaxはまだ発見されていなかったため、クエリ文字列を取得するためだけにフォームを解析する(送信時に自分で作成する)ことは、おそらくあまり意味がありませんでした。今日は難しいです...ところで、script.aculo.usと比較すると、プロトタイプは素晴らしいです。:)
Stein G. Strindhaug '25年


6

ライブラリを使用したくない場合、これは同じフォーム要素タイプのほとんど/すべてをカバーするはずです。

function serialize(form) {
  if (!form || !form.elements) return;

  var serial = [], i, j, first;
  var add = function (name, value) {
    serial.push(encodeURIComponent(name) + '=' + encodeURIComponent(value));
  }

  var elems = form.elements;
  for (i = 0; i < elems.length; i += 1, first = false) {
    if (elems[i].name.length > 0) { /* don't include unnamed elements */
      switch (elems[i].type) {
        case 'select-one': first = true;
        case 'select-multiple':
          for (j = 0; j < elems[i].options.length; j += 1)
            if (elems[i].options[j].selected) {
              add(elems[i].name, elems[i].options[j].value);
              if (first) break; /* stop searching for select-one */
            }
          break;
        case 'checkbox':
        case 'radio': if (!elems[i].checked) break; /* else continue */
        default: add(elems[i].name, elems[i].value); break;
      }
    }
  }

  return serial.join('&');
}

ありがとう!私は元のポスターと同じ問題に直面していただけで、あなたの機能はまさに私が必要としていたものでした。
dagw 2009

4

プロトタイプでこれを行うためのフォームは実際には必要ありません。Object.toQueryString関数を使用するだけです

Object.toQueryString({ action: 'ship', order_id: 123, fees: ['f1', 'f2'], 'label': 'a demo' })

// -> 'action=ship&order_id=123&fees=f1&fees=f2&label=a%20demo'

4
確かに、あなたは10年近く前に答えましたが、このコードは現在非推奨です。
SEoF 2018年

4

あなたは、今日でそれを行うことができますFormDataし、URLSearchParams何をループする必要なし。

const formData = new FormData(form);
const searchParams = new URLSearchParams(formData);
const queryString = searchParams.toString();

ただし、古いブラウザにはポリフィルが必要です。


3

私自身は完全に確信しているわけではありません。jQueryがある程度それを行ったことを思い出しますが、phpフレンドリーな方法はもちろん、階層レコードをまったく処理しません。

私が確かに知っていることの1つは、URLを作成して製品をdomに貼り付けるときに、文字列の接着剤を使用してそれを行わないでください。そうしないと、便利なページブレーカーが開かれます。

たとえば、特定の広告ソフトウェアは、フラッシュを実行するもののバージョン文字列をインライン化します。これは、アドビの一般的な単純な文字列の場合は問題ありませんが、非常にナイーブであり、gnashのバージョン文字列にURLを備えた完全なGPL著作権ライセンスが含まれているため、Gnashをインストールした人にとっては厄介な混乱に陥ります。および<a href>タグ。文字列接着剤の広告生成ツールでこれを使用すると、ページが開いて不均衡なHTMLが表示されます。

物語の教訓:

   var foo = document.createElement("elementnamehere"); 
   foo.attribute = allUserSpecifiedDataConsideredDangerousHere; 
   somenode.appendChild(foo); 

ない:

   document.write("<elementnamehere attribute=\"" 
        + ilovebrokenwebsites 
        + "\">" 
        + stringdata 
        + "</elementnamehere>");

Googleはこのトリックを学ぶ必要があります。私は問題を報告しようとしました、彼らは気にしないようです。


右に。document.writeがあるので、とにかく、1995。

2

スタインが言うように、http: //www.prototypejs.orgからのプロトタイプJavaScriptライブラリを使用できます。JSを含めると、非常に簡単になり、$('formName').serialize()必要なものが返されます。



2

少し冗長かもしれませんが、ここでいくつかの答えに基づいて私が見つけた最もきれいな方法:

const params: {
   key1: 'value1',
   key2: 'value2',
   key3: 'value3',
}

const esc = encodeURIComponent;
const query = Object.keys(params)
  .map(k => esc(k) + '=' + esc(params[k]))
  .join('&');

return fetch('my-url', {
  method: 'POST',
  headers: {'Content-Type': 'application/x-www-form-urlencoded'},
  body: query,
})

ソース


1

これらの回答は非常に役に立ちますが、完全なURLを作成するのに役立つ別の回答を追加したいと思います。これは、ベースCONCATあなたを助けることができるurlpathhashparameters

var url = buildUrl('http://mywebsite.com', {
        path: 'about',
        hash: 'contact',
        queryParams: {
            'var1': 'value',
            'var2': 'value2',
            'arr[]' : 'foo'
        }
    });
    console.log(url);

npm https://www.npmjs.com/package/build-urlからダウンロードできます

デモ:

;(function () {
  'use strict';

  var root = this;
  var previousBuildUrl = root.buildUrl;

  var buildUrl = function (url, options) {
    var queryString = [];
    var key;
    var builtUrl;
    var caseChange; 
    
    // 'lowerCase' parameter default = false,  
    if (options && options.lowerCase) {
        caseChange = !!options.lowerCase;
    } else {
        caseChange = false;
    }

    if (url === null) {
      builtUrl = '';
    } else if (typeof(url) === 'object') {
      builtUrl = '';
      options = url;
    } else {
      builtUrl = url;
    }

    if(builtUrl && builtUrl[builtUrl.length - 1] === '/') {
      builtUrl = builtUrl.slice(0, -1);
    } 

    if (options) {
      if (options.path) {
          var localVar = String(options.path).trim(); 
          if (caseChange) {
            localVar = localVar.toLowerCase();
          }
          if (localVar.indexOf('/') === 0) {
              builtUrl += localVar;
          } else {
            builtUrl += '/' + localVar;
          }
      }

      if (options.queryParams) {
        for (key in options.queryParams) {
          if (options.queryParams.hasOwnProperty(key) && options.queryParams[key] !== void 0) {
            var encodedParam;
            if (options.disableCSV && Array.isArray(options.queryParams[key]) && options.queryParams[key].length) {
              for(var i = 0; i < options.queryParams[key].length; i++) {
                encodedParam = encodeURIComponent(String(options.queryParams[key][i]).trim());
                queryString.push(key + '=' + encodedParam);
              }
            } else {              
              if (caseChange) {
                encodedParam = encodeURIComponent(String(options.queryParams[key]).trim().toLowerCase());
              }
              else {
                encodedParam = encodeURIComponent(String(options.queryParams[key]).trim());
              }
              queryString.push(key + '=' + encodedParam);
            }
          }
        }
        builtUrl += '?' + queryString.join('&');
      }

      if (options.hash) {
        if(caseChange)
            builtUrl += '#' + String(options.hash).trim().toLowerCase();
        else
            builtUrl += '#' + String(options.hash).trim();
      }
    } 
    return builtUrl;
  };

  buildUrl.noConflict = function () {
    root.buildUrl = previousBuildUrl;
    return buildUrl;
  };

  if (typeof(exports) !== 'undefined') {
    if (typeof(module) !== 'undefined' && module.exports) {
      exports = module.exports = buildUrl;
    }
    exports.buildUrl = buildUrl;
  } else {
    root.buildUrl = buildUrl;
  }
}).call(this);


var url = buildUrl('http://mywebsite.com', {
		path: 'about',
		hash: 'contact',
		queryParams: {
			'var1': 'value',
			'var2': 'value2',
			'arr[]' : 'foo'
		}
	});
	console.log(url);


1

私はこれが非常に遅い答えであることを知っていますが、非常にうまくいきます...

var obj = {
a:"a",
b:"b"
}

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

注:object.entriesはキーと値のペアを返します

上記の行からの出力は、a = a&b = bになります。

それが誰かを助けることを願っています。

ハッピーコーディング...


0

質問に答えるのはおそらく遅すぎます。
同じ質問があり、URLを作成するために文字列を追加し続けたくありませんでした。それで、techhouseが説明したように、私は$ .paramを使い始めました。
また、URLを簡単に作成できるURI.jsライブラリも見つけました。あなたに役立ついくつかの例があります:URI.js Documentation
以下はその1つです。

var uri = new URI("?hello=world");
uri.setSearch("hello", "mars"); // returns the URI instance for chaining
// uri == "?hello=mars"

uri.setSearch({ foo: "bar", goodbye : ["world", "mars"] });
// uri == "?hello=mars&foo=bar&goodbye=world&goodbye=mars"

uri.setSearch("goodbye", "sun");
// uri == "?hello=mars&foo=bar&goodbye=sun"

// CAUTION: beware of arrays, the following are not quite the same
// If you're dealing with PHP, you probably want the latter…
uri.setSearch("foo", ["bar", "baz"]);
uri.setSearch("foo[]", ["bar", "baz"]);`

0

var params = { width:1680, height:1050 };
var str = jQuery.param( params );

console.log(str)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

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