Javascript로 쿼리 문자열을 작성하는 방법


답변:


-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
그것은 단지 나입니까, 아니면 전혀 질문에 대답하지 않습니까? 그는 매핑 된 배열이 아닌 쿼리 문자열을 요청했습니다.
Jake Wilson

2
@JakeWilson 네,이 답변은이 질문의 절반에 해당합니다. 배열은 여전히 ​​쿼리 문자열 형식이어야합니다.
Hutch Moore

9
와우 나는 그때 JS에서 멍청한 놈 이었어 야했다. new Array()사전을 초기화하는 데 사용 합니다. 그러나 다시, 요즘 코드는 내가 쓸만한 쓰레기보다 훨씬 깨끗해 보입니다!
hasen sep

2
@ hasen 아마도이 답변을 편집하거나 음, 삭제 하시겠습니까? 그것은 스크롤 할 때마다 점점 더 많은 downvotes가 있습니다 = -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

9
3) 모든 브라우저가 화살표 기능 구문을 지원하지는 않습니다 (ES5 필요). 모든 브라우저를 지원하고 부분을 인코딩하려면 위의 .map ()을 .map (function (k) {return encodeURIComponent (k) + '='+ encodeURIComponent (params [k]);})로 바꾸십시오.
John Deighan

1
아름다운. 정말 아름답습니다.
Mikko Ohtamaa

9
"충분한 jquery"
Eugene Pankov

1
@ user1738579 ES5 이외의 예제도 포함하도록 답변을 편집했습니다.
Taylor Edmiston

134

jQuery를 사용하는 경우 체크 아웃 할 수 있습니다 jQuery.param() http://api.jquery.com/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()

95
jQuery !== JavaScript
gphilip

14
@gphilip "JQuery를 사용하는 경우 ..."로 응답을 시작한 이유입니다. 그렇지 않으면 바닐라 JS로 구현하려면 jQuery.param()여기 github.com/jquery/jquery/blob/master/src/serialize.js 의 구현을 검사 할 수 있습니다 :)
Klemen Tušar

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")
:)

TS는 일반 객체 사용에 대해 경고하지만 그럼에도 불구하고 잘 작동합니다.
Vadorequest

@pomber 정의되지 않은 항목을 필터링하는 좋은 아이디어가 있습니까?
Dan Gayle

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 등과 같은 인기있는 자바 스크립트 프레임 워크 중 하나에 이와 비슷한 내장 함수가 있습니까?
사무엘

보다 강력한 네이티브 자바 스크립트 솔루션에 있습니다 stackoverflow.com/a/1714899/1269037
댄 Dascalescu

가장 현명한 구현, 왜 new Array실제로 객체로 사용 하는 동안 초기화해야 합니까? o, O
Umut Sirin

@ UmutSirin Lol 예, 당시 Javascript에 대해서는별로 몰랐습니다. xD PHP 배열처럼 취급한다고 생각합니다. 원하는 경우 리팩토링하십시오.
Michael

@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 대신
보리스

10

아니, 표준 자바 스크립트가 내장되어 있다고 생각하지 않지만, 프로토 타입 JS는 기능 (확실히 다른 대부분의 JS 프레임 워크도 가지고 있지만, 내가 그들을 모르는)가 호출이 직렬화를 .

Prototype JS를 추천 할 수 있습니다. 내가 실제로 발견 한 유일한 단점은 크기 (수백 kb)와 범위 (아약스, 돔 등을위한 많은 코드)라는 것을 알았습니다. 따라서 폼 serializer 만 원한다면 과잉이며 Ajax 기능 만 원한다면 엄격하게 말하면 과잉입니다. 주의하지 않으면 너무 많은 "마법"을 수행한다는 것을 알 수 있습니다 (예를 들어 요소를 찾기 위해 프로토 타입 JS 함수로 터치하는 모든 dom 요소를 확장하는 것과 같이).


내장 된 것이 있는지 궁금합니다. 있어야 할 것 같습니다. 나는 프로토 타입을 싫어하지만, 그 : 당신에 대해 보유하고 있지 않다

JavaScript가 디자인되었을 때 Ajax는 아직 발견되지 않았기 때문에 쿼리 문자열을 얻기 위해 양식을 구문 분석하는 경우 (제출시 자체 작성되는) 아마도 의미가 없었습니다. 오늘날 그것은 어렵습니다 ... Btw, script.aculo.us와 비교할 때, 프로토 타입은 훌륭 합니다. :)
Stein G. Strindhaug

10

querystring 이 도움이 될 수 있습니다.

그래서, 당신은 할 수 있습니다

const querystring = require('querystring')

url += '?' + querystring.stringify(parameters)

3
프론트 엔드 애플리케이션을 위해 당신은 또한 고려해 볼 수 있습니다 npmjs.com/package/qs
로버트 Pankowecki

@RobertPankowecki, 예, qs는 더 좋으며 이미 내 무기고에 있습니다.
ImLeo

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

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

4

당신과 함께 요즘 그렇게 할 수 FormDataURLSearchParams아무것도를 반복 할 필요없이.

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

그러나 오래된 브라우저에는 폴리 필이 필요합니다.


3

나는 전적으로 자신이 확실하지 않습니다 .jQuery가 어느 정도까지 수행 한 것을 기억하지만 PHP 친화적 인 방식으로 계층 적 레코드를 전혀 처리하지는 않습니다.

내가 확실히 알고있는 한 가지는 URL을 만들고 제품을 DOM에 집어 넣을 때 문자열 접착제를 사용하지 말고 편리한 페이지 차단기를 여는 것입니다.

예를 들어 특정 광고 소프트웨어는 플래시를 실행하는 모든 버전의 버전 문자열을 인라인합니다. GNASH의 버전 문자열에 URL이 포함 된 GPL 저작권 라이센스가 완전히 포함되어 있기 때문에 Gnash를 설치 한 사람들에게는 당황스럽고 엉망이됩니다. 및 <a href> 태그. 이를 문자열 접착제 광고주 생성기에서 사용하면 페이지가 열리고 HTML에서 불균형 한 HTML이 나타납니다.

이 이야기의 교훈:

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

아니:

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

Google은이 트릭을 배워야합니다. 문제를보고하려고했지만 걱정하지 않는 것 같습니다.


바로 document.write를이다 그래서 어쨌든, 1995.

2

Stein이 말했듯이 http://www.prototypejs.org 의 프로토 타입 자바 스크립트 라이브러리를 사용할 수 있습니다 . 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 당신을 도울 수 url, path, hashparameters.

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 .
다음 중 하나입니다.

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.