객체를 URL 쿼리 매개 변수 목록으로 직렬화하는 방법은 무엇입니까?


163

JavaScript의 키를 모르고 Object어떻게하면 다음과 같이 바꿀 수 있습니까?

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

obj[param4] = 'yetanother';

...으로...

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

...?


1
재귀 솔루션을 찾고 계십니까?
Jared Farrish 2011

1
@Jared 나는 재귀 솔루션 : 추가
알렉스

@alex-감사합니다. 더 복잡한 문제에 대해 경험이 많은 사람들의 답변을 보는 것이 좋습니다. :)
Jared Farrish 2011

2
@Jared 알다시피, 저는 제 자신을 경험 많은 JavaScript 개발자 라고 생각하지 않습니다 . 더 많은처럼 작동 때까지 '해킹 : 남자
알렉스

@alex-오 그래, 나도. 그러나 당신이 모은 것은 내가 접근했을 때와 어떻게 비교할 것인가? 나는 끊임없이 놀랐다.
Jared Farrish 2011

답변:


107
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

4
@bobsoap : @aroth가 나보다 조금 앞서 있다고 생각하기 때문에 @aroth에 다른 모든 것들이 동등하다는 것을 똑같이 줄 것입니다.
user113716

3
obj [key]를 encodeURIComponent ()로 래핑하면 안 되나요? 'somethingelse'가 'something & else'이면 어떻게 되나요?
James S

1
나는 이것이 받아 들여지는 대답 이 아니 거나이 stackoverflow 스레드의 거의 모든 대답이 아니 어야한다고 확신합니다 . 주된 이유는 아래의 @zac의 대답을 제외 하고는이 객체를 올바르게 인코딩하는 것을 제외하고는 아무도 없기 때문에 { 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?" };@UnLoCo가 작동하는 NPM 라이브러리를 제안한 것처럼 보입니다. 이는 jQuery에서 작동하는 param 메서드를 독립형으로 가져옵니다.
Wes

137

jQuery를 사용하는 경우 GET XHR 요청의 옵션을 매개 변수화하는 데 사용합니다.

$.param( obj )

http://api.jquery.com/jQuery.param/


대부분의 다른 anser는 중첩 된 개체에 적합하지 않았습니다. 이것은 트릭을 수행합니다. 감사!
Julesezaar

125

우아한 것 : (최신 브라우저 또는 노드를 실행하고 있다고 가정)

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

3
이는 객체에 중첩 된 속성이 있으면 분해됩니다.
Sean the Bean

2
ES2015 답변 변경을 인코딩하려면 :=${encodeURIComponent(val)}
BBlackwo

74

종속성이없는 한 줄 :

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'.


13
이 마일으로 최고의 답변입니다
hraban

참고 : 예 필요 / 수입해야 노드 <10const { URLSearchParams } = require("url");
groovecoder

1
@HonsaStunna 내가 URL 매개 변수에 다차원 개체를 퍼팅에 대해 생각해 본 적이 없는데, 보통 그것을 위해 JSON과 POST를 사용
jfunk

1
이 값과 null 값에주의하십시오.
Xaraxia

URLSearchParams를 지원할 대상 브라우저가 있는지 확인해야합니다. 예를 들어 IE11은 그렇지 않습니다. caniuse.com/?search=URLSearchParams
Peter T.

27

ES2017 접근 방식

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

2
기술적으로 ES2017 .
Nick Zalutskiy

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

한 단계 깊이 ...

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 2011-07-04

내가 원하는 것보다 더 안전한 경우 +1 : .hasOwnProperty(prop).
user113716 2011-07-04

이것은 대단합니다-지금은 1 레벨 만 필요하지만 재귀 함수가 있으면 좋습니다. 추가해 주셔서 감사합니다!
bobsoap

1
@ ripper234 요구 사항에 맞다면 그 방법을 사용하지 않아도됩니다.
alex

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

5

재귀 함수에 대해 그렇게 큰 일을 했으므로 여기에 내 버전이 있습니다.

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) delimiter = delimiter || '&';인수 기본값으로 사용할 수 있습니다 (그리고 철자를 잘못 입력했습니다) (c) 반복 for ( in )은 프로토 타입 체인의 것들을 포함하여 모든 열거 가능한 속성을 반복합니다 ( obj.hasOwnProperty()이것을 방어합니다) (d)는 typeof거짓말을 몇 가지 숫자가 될 수있다 예를 들어, 일이 무엇인지에 대해 Object로 구성하는 경우 Number()생성자 (예) Arraypush()에 비해 회원 (F)를 추가하는 방법을 true중복입니다. 나는 멍청한 놈이지만 피드백을 원했습니다! :)
alex

1
... 그리고 당신이 Crockford가 모든 것에 대해 옳다고 생각한다면, 스위치 케이스가 빠져 나가게해서는 안됩니다. 나는 그에 대해 동의하지 않는다. : D
알렉스

@alex-감사합니다. a) 처음에는 그것을 가지고 있었고 늦었고 졸 렸습니다. b) 개선이 무엇인지 확실하지 않고 두 번째도 수면이 부족한 순간이었습니다. c) 왜 사용했는지 궁금합니다 hasOwnProperty(). d) 그것은 확실히 사실이며 좋은 지적이다. e) push()또는 pop()방법 을 사용해 본 적이 없습니다 . f) break여부 break, 그게 문제입니다. 자세한 입력에 감사드립니다. :)
Jared Farrish 2011

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

쿼리에 배열이있을 때 유용한 코드 :

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
new URLSearchParams({hello: 'world', foo: 'bar' }).toString()

일을하는 것 같습니다. 에 대한 필요가 없습니다 encodeURIComponent. 출력hello=world&foo=bar


1
이것은 내가 게시 한 답변에 대한 중복 답변입니다.
jfunk

4

NodeJS 13.1 이상을 사용하는 경우 네이티브 쿼리 문자열 모듈을 사용하여 쿼리 문자열을 구문 분석 할 수 있습니다.

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

3

주어진 객체를 기반으로 적절한 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"

벽에
걸게

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>


2
var str = '';

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

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

이 기회를 줘.

예 : http://jsfiddle.net/T2UWT/


1
@Jared : 루프보다 덜 효율적입니다.
user113716

@Jared : Qs 및 As 아래에 사용자 이름이 필요하지 않습니다. 알림은 자동입니다.
user113716

"낮은 성능"? 임의의 개체를 전달하고 GET 문자열을 반환하려면 성능과 어떤 관련이 있습니까?
Jared Farrish 2011

@Jared : 미안하지만 당신의 의미를 이해하지 못하는 것 같습니다. 루프가 아닌 재귀 함수 호출을 사용하도록 제안하는 경우 재귀 함수가 루프보다 더 느리게 수행 될 것이라고 확신합니다. 내가 당신의 요점을 오해 했습니까?
user113716

1
글쎄요, 모르겠어요. 객체를 보내고 해당 객체의 문자열 연결 GET 한정 버전을 출력하는 함수가 있다면 단일 루프가 항상 입력을 처리한다고 생각하지 않습니다. 물론 단일 레벨 루프는 항상 다중 레벨 재귀보다 "성능이 우수하지만"단일 레벨 루프는 다중 레벨 객체 인 IMO를 처리하지도 않습니다.
Jared Farrish 2011

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 쿼리 문자열을 사용할 수 있습니다.

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

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

0

const obj = { id: 1, name: 'Neel' };
let str = '';
str = Object.entries(obj).map(([key, val]) => `${key}=${val}`).join('&');
console.log(str);


0

Axiosinfinite depth:

<pre>
    <style>
      textarea {
        width: 80%;
        margin-bottom: 20px;
      }
      label {
        font-size: 18px;
        font-weight: bold;
      }
    </style>
    <label>URI</label>
    <textarea id="uri"  rows="7"></textarea>
    <label>All Defaults (Bonus): </label>
    <textarea id="defaults" rows="20"></textarea>
</pre>

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

<script>
  const instance = axios.create({
    baseUrl: 'http://my-api-server',
    url: '/user'
  })
  const uri = instance.getUri({
    params: {
      id: '1234',
      favFruits: [
        'banana',
        'apple',
        'strawberry'
      ],
      carConfig: {
        items: ['keys', 'laptop'],
        type: 'sedan',
        other: {
          music: ['on', 'off', {
            foo: 'bar'
          }]
        }
      }
    }
  })
  const defaults = JSON.stringify(instance.defaults, null, 2)
  document.getElementById('uri').value = uri
  document.getElementById('defaults').value = defaults
</script>

행운을 빕니다...

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.