การเข้ารหัสสตริงเคียวรีของวัตถุ Javascript


481

คุณรู้วิธีที่ง่ายและรวดเร็วในการเข้ารหัส Javascript Object ในstringที่ฉันสามารถส่งผ่านGETคำขอได้หรือไม่?

ไม่jQueryไม่มีกรอบอื่น ๆ - แค่ Javascript ธรรมดา :)


ทำไม JQuery ถึงไม่สามารถแก้ปัญหาหากมีวิธีการที่เหมาะสมสำหรับโซลูชันของคุณ
eaglei22

@ eaglei22 เพราะในขณะที่ฉันทำงานเกี่ยวกับโครงการสำหรับอุปกรณ์กล่องรับสัญญาณ IPTV และไม่อนุญาตให้ใช้ไลบรารีภายนอก ;-)
napolux

1
ขอบคุณสำหรับคำตอบ ฉันเห็นสเปคนี้เป็นครั้งคราวและมักสงสัยว่าทำไม ดีตอนนี้ฉันได้หนึ่งขอบคุณ! :)
eaglei22

9
@ eaglei22 เพราะบางครั้งคุณไม่ต้องการโหลดไลบรารี่ขนาดใหญ่เพื่อรับหนึ่งองค์ประกอบตามรหัส
Aaron Harun

เบราว์เซอร์ส่วนใหญ่รองรับURLSearchParamsตอนนี้ ...
mb21

คำตอบ:


810

แบบนี้?

serialize = function(obj) {
  var str = [];
  for (var p in obj)
    if (obj.hasOwnProperty(p)) {
      str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
    }
  return str.join("&");
}

console.log(serialize({
  foo: "hi there",
  bar: "100%"
}));
// foo=hi%20there&bar=100%25

แก้ไข: อันนี้ยังแปลงวัตถุแบบเรียกซ้ำ (โดยใช้สัญกรณ์ php "array" สำหรับสตริงการสืบค้น)

serialize = function(obj, prefix) {
  var str = [],
    p;
  for (p in obj) {
    if (obj.hasOwnProperty(p)) {
      var k = prefix ? prefix + "[" + p + "]" : p,
        v = obj[p];
      str.push((v !== null && typeof v === "object") ?
        serialize(v, k) :
        encodeURIComponent(k) + "=" + encodeURIComponent(v));
    }
  }
  return str.join("&");
}

console.log(serialize({
  foo: "hi there",
  bar: {
    blah: 123,
    quux: [1, 2, 3]
  }
}));
// foo=hi%20there&bar%5Bblah%5D=123&bar%5Bquux%5D%5B0%5D=1&bar%5Bquux%5D%5B1%5D=2&bar%5Bquux%5D%5B2%5D=3


2
จะไม่ได้รับ {foo: [1,2,3] บาร์: "100%"} หรือไม่
Quentin

1
@Ofri: สำหรับคำขอ POST ไปยังเซิร์ฟเวอร์ที่ติดตั้งเพื่อรับ JSON เป็นตัวเลือกที่ดี สำหรับคำขอ GET หากคุณกำลังส่งอะไรอื่นนอกจากพารามิเตอร์ง่ายๆสองสามตัวไปยังเซิร์ฟเวอร์แสดงว่าการออกแบบของคุณผิด
Tim Down

2
@Marcel นั่นเป็นเพราะฟังก์ชั่นไม่ได้ตรวจสอบ hasOwnProperty ฉันได้อัพเดทซอของคุณแล้วตอนนี้ก็ทำเช่นนั้น: jsfiddle.net/rudiedirkx/U5Tyb/1
Rudie

1
@TimDown เกี่ยวกับความคิดเห็นของคุณส่งพารามิเตอร์ง่าย ๆ ในคำขอ GET ผมไม่เห็นด้วย. การจัดกลุ่มพารามิเตอร์ในอาร์เรย์อาจเปลี่ยนเป็นประโยชน์เมื่อ PHP ในฝั่งเซิร์ฟเวอร์พบว่าอาเรย์เชื่อมโยงที่พร้อมใช้งานคงที่ ฉันไม่สามารถเห็นได้ว่าทำไมสิ่งนี้จึงผิดปกติกับการออกแบบ
Savas Vedova

1
จำเป็นต้องใช้ 'if (obj.hasOwnProperty (prop)) หรือไม่ hasOwnProperty สำหรับในวงคำสั่งเพียงกว่าคุณสมบัติของวัตถุเพื่อเรียกเสมอประเมินให้เป็นจริง
อานนท์

231

jQuery มีฟังก์ชั่นสำหรับสิ่งนี้jQuery.param()หากคุณใช้อยู่แล้วคุณสามารถใช้มันได้ที่: http://api.jquery.com/jquery.param/

ตัวอย่าง:

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

str ตอนนี้มี width=1680&height=1050


119
อ้าง Napolux (สหกรณ์): "เพียงธรรมดาจาวาสคริ" : P
Sk8erPeter

6
jQuery.param () มีพฤติกรรมที่น่ากลัว ลองเรียกใช้งาน var a = []; a [2564] = 12; console.log (jQuery.param ({propertylist: a})); เพื่อดูว่าฉันหมายถึงอะไร
Akond

13
@akond เอกสาร jQuery กล่าวโดยเฉพาะว่าคุณไม่สามารถผ่านไปในอาร์เรย์เปล่าได้
Ariel

4
@Ariel เขาไม่ได้ผ่านชุดที่เปลือยเปล่า เขาผ่านในอาร์เรย์ที่มีเพียงหนึ่งค่าที่ดัชนี 2564. เพื่อแสดงให้เห็น: ผลการค้นหาในvar a = []; a[5] = 'foo'; jQuery.param({ parameters: a }); "parameters[]=&parameters[]=&parameters[]=&parameters[]=&parameters[]=&parameters[]=foo"ซึ่งในขณะที่ถูกต้องอาจไม่ใช่สิ่งที่คุณคาดหวัง
Chris Hall

4
คำถามได้ถามโดยเฉพาะ Vanilla JS
Bug Hunter 219

189

เพียงแค่ใช้URLSearchParamsนี้ผลงานในเบราว์เซอร์ในปัจจุบันทั้งหมด

new URLSearchParams(object).toString()

5
ไม่เพราะไม่ทำวัตถุแบบเรียกซ้ำ
Eddie Monge Jr

ไม่ทำงานบนวัตถุที่ซ้อนกัน let j = { m: 5, n: { k: 1 } }; new URLSearchParams(j).toString(); // result "m=5&n=%5Bobject+Object%5D"
hitautodestruct

19
@EddieMongeJr สตริงการสืบค้นเป็นคู่ค่าคีย์โดยการออกแบบคุณไม่ควรแม้แต่ต้องการเรียงลำดับวัตถุที่ซ้อนกันคำตอบนี้เป็นวิธีที่ทันสมัยในการไป จำเป็นต้องมีการลงคะแนน
Romain Durand

5
ใช่พวกเขาเป็นคู่ของค่าคีย์ แต่ไม่มีอะไรที่บอกว่าค่าไม่สามารถเป็นวัตถุที่เข้ารหัสสตริงได้ นอกจากนี้คำถามเดิมขอให้ "Javascript Object เป็นสตริง" ซึ่งสามารถมีคุณสมบัติซ้อนกัน
Eddie Monge Jr

@EddieMongeJr แม้แต่คำตอบที่ยอมรับได้ (และคำตอบอื่น ๆ หลังจากดูแบบสั้น ๆ ) ไม่สนับสนุนวัตถุที่ซ้อนกัน คุณสามารถstringifyเลือกวัตถุที่ซ้อนกันได้ก่อนที่คุณจะสามารถURLSearchParams
Mosh Feu

128
Object.keys(obj).reduce(function(a,k){a.push(k+'='+encodeURIComponent(obj[k]));return a},[]).join('&')

แก้ไข: ฉันชอบหนึ่งซับ แต่ฉันคิดว่ามันจะเป็นคำตอบที่ได้รับความนิยมมากขึ้นถ้าตรงกับคำตอบที่ได้รับการยอมรับ semantically:

function serialize( obj ) {
    let str = '?' + Object.keys(obj).reduce(function(a, k){
        a.push(k + '=' + encodeURIComponent(obj[k]));
        return a;
    }, []).join('&');
    return str;
}

1
บรรทัดเฉพาะสำหรับฟังก์ชัน reduct จะช่วยปรับปรุงความสามารถในการอ่านได้อย่างมาก
Aurelien Ribon

54
การใช้. map () แทนที่จะเป็น. reduce () จะง่ายยิ่งขึ้น: Object.keys(obj).map(k => k + '=' + encodeURIComponent(obj[k])).join('&')
Jannes

2
เพิ่งทราบว่าObject.keysมีเฉพาะใน IE> = 9
Johnston

5
ปรับปรุงรหัส @Jannes เพิ่มเติมโดยใช้เทมเพลต ES6 แทนการต่อข้อมูล -Object.keys(obj).map(k => `${k}=${encodeURIComponent(obj[k])}`).join('&')
csilk

1
ในกรณีที่กุญแจของคุณจำเป็นต้องมีการเข้ารหัส UComponent ❤️ด้วย: Object.entries(obj).map(e => e.map(ee => encodeURIComponent(ee)).join('=')).join('&');
Blaise

112

นี่คือซับใน ES6:

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

แทนที่ key w / k และคุณเป็นทอง
Jamie Kudla

17
คำเตือน! ใช้ได้กับวัตถุที่ตื้นเท่านั้น หากคุณมีคุณสมบัติระดับบนสุดที่เป็นวัตถุอื่นหนึ่งซับนี้จะส่งออก "key =% 5Bobject% 20Object% 5D" เหมือนหัวขึ้น
Andrew Allbright

4
นอกจากนี้จะไม่คายอาร์เรย์ ฉันได้export?actions[]=finance,create,editเมื่อมันควรจะexport?actions[]=finance&actions[]=create&actions[]=editเป็นตามมาตรฐานอันยิ่งใหญ่
darkbluesun

3
อาเรย์นั้นค่อนข้างจะ "คุณอยู่คนเดียว" เสมอเพราะอาร์กิวเมนต์ของ URL เป็นเพียงสตริงเท่าที่ข้อมูลจำเพาะนั้นเกี่ยวข้องดังนั้นคุณจึงอยู่ในสถานะเบ็ดเสร็จเพื่อให้ทุกสิ่งที่ไม่ใช่สายเดียวที่จะอ่านได้อย่างถูกต้องโดยเซิร์ฟเวอร์ คุณกำลังโทร actions[]สัญกรณ์ PHP คือ; Django ใช้หลายactionตัวแทน (ไม่มี[]คำต่อท้าย); ORM / CMS อื่น ๆ ต้องการรายการที่คั่นด้วยเครื่องหมายจุลภาค ฯลฯ ดังนั้น "ถ้าไม่ใช่สตริงอย่างง่ายอันดับแรกให้แน่ใจว่าคุณรู้ว่าเซิร์ฟเวอร์ของคุณต้องการอะไร"
Kamermans 'Pomax' ของไมค์

ทางออกที่หรูหรามาก!
Anh Tran

51

ด้วย Node.js v6.6.3

const querystring = require('querystring')

const obj = {
  foo: 'bar',
  baz: 'tor'
}

let result = querystring.stringify(obj)
// foo=bar&baz=tor

การอ้างอิง: https://nodejs.org/api/querystring.html


8
สิ่งนี้ไม่ควรถูกลดระดับลง IMO หากเป็น JS บนเซิร์ฟเวอร์นี่ควรเป็นคำตอบที่ถูกต้อง
Michael Benin

4
ดูเหมือนว่าจะไม่รองรับวัตถุที่ซ้อนกัน
Yarin Gold

43

ฉันขอแนะนำให้ใช้URLSearchParamsอินเทอร์เฟซ:

const searchParams = new URLSearchParams();
const search = {foo: "hi there", bar: "100%" };
Object.keys(search).forEach(key => searchParams.append(key, search[key]));
console.log(searchParams.toString())

หรือโดยการส่งผ่านวัตถุค้นหาไปยังตัวสร้างเช่นนี้

const obj = {foo: "hi there", bar: "100%" };
const params = new URLSearchParams(obj).toString();

1
คำแนะนำที่น่าสนใจ แต่โปรดทราบว่าการสนับสนุนเบราว์เซอร์สำหรับคุณสมบัตินี้ยังคงเป็นหย่อม
mrec

หากคุณไม่สนับสนุน IE (ซึ่งเป็นเรื่องปกติในขณะนี้) และบางรุ่นสำหรับมือถือนี่เป็นคำตอบที่ดีที่สุดเนื่องจากเป็น JavaScript ธรรมดา
Marcos Sandrini

24

การแก้ไขเล็กน้อยสำหรับโซลูชันที่ยอมรับโดยผู้ใช้ 187291:

serialize = function(obj) {
   var str = [];
   for(var p in obj){
       if (obj.hasOwnProperty(p)) {
           str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
       }
   }
   return str.join("&");
}

การตรวจสอบ hasOwnProperty บนวัตถุทำให้ JSLint / JSHint มีความสุขและช่วยป้องกันวิธีการจัดลำดับวัตถุหรือสิ่งของอื่น ๆ โดยไม่ตั้งใจหากวัตถุนั้นเป็นพจนานุกรมแบบง่าย ดูย่อหน้าสำหรับคำสั่งในหน้านี้: http://javascript.crockford.com/code.html


14

ทุกคนดูเหมือนว่าจะใส่หนึ่งซับของเขาที่นี่เพื่อไปที่นี่ของฉัน:

const encoded = Object.entries(obj).map(([k, v]) => `${k}=${encodeURIComponent(v)}`).join("&");

1
ไม่รองรับ Object.entries ใน IE
MBouwman

@ MBouwman แน่นอน IE เสียเกินกว่าความดีและความชั่วนั่นคือเหตุผลว่าทำไมคุณต้องใช้ babel / core-js
chpio

@chpio Babel / core-js ไม่รองรับ Object.entries ถ้าฉันพูดถูก
MBouwman

หลักมีการสนับสนุนสำหรับ Object.entries: github.com/zloirock/core-js/blob/master/ …และแม้แต่การแปลงเก่ารันไทม์ corejs2 babel ก็รองรับgithub.com/babel/babel/babel/blob/
......

12

คุณต้องการส่งวัตถุโดยพลการหรือไม่? ถ้าเป็นเช่นนั้น GET เป็นแนวคิดที่ไม่ดีเนื่องจากมีข้อ จำกัด เกี่ยวกับความยาวของ URL ที่ตัวแทนผู้ใช้และเว็บเซิร์ฟเวอร์จะยอมรับ ข้อเสนอแนะของฉันคือการสร้างอาร์เรย์ของคู่ชื่อ - ค่าที่จะส่งแล้วสร้างสตริงแบบสอบถาม:

function QueryStringBuilder() {
    var nameValues = [];

    this.add = function(name, value) {
        nameValues.push( {name: name, value: value} );
    };

    this.toQueryString = function() {
        var segments = [], nameValue;
        for (var i = 0, len = nameValues.length; i < len; i++) {
            nameValue = nameValues[i];
            segments[i] = encodeURIComponent(nameValue.name) + "=" + encodeURIComponent(nameValue.value);
        }
        return segments.join("&");
    };
}

var qsb = new QueryStringBuilder();
qsb.add("veg", "cabbage");
qsb.add("vegCount", "5");

alert( qsb.toQueryString() );

11

Rails / PHP Style Query Builder

วิธีการนี้จะแปลงวัตถุ Javascript URI Query Stringเป็น จัดการกับอาร์เรย์และวัตถุที่ซ้อนกัน (ในRails/ PHPไวยากรณ์):

function serializeQuery(params, prefix) {
  const query = Object.keys(params).map((key) => {
    const value  = params[key];

    if (params.constructor === Array)
      key = `${prefix}[]`;
    else if (params.constructor === Object)
      key = (prefix ? `${prefix}[${key}]` : key);

    if (typeof value === 'object')
      return serializeQuery(value, key);
    else
      return `${key}=${encodeURIComponent(value)}`;
  });

  return [].concat.apply([], query).join('&');
}

ตัวอย่างการใช้งาน:

let params = {
  a: 100,
  b: 'has spaces',
  c: [1, 2, 3],
  d: { x: 9, y: 8}
}

serializeQuery(params)
// returns 'a=100&b=has%20spaces&c[]=1&c[]=2&c[]=3&d[x]=9&d[y]=8

ตัวอย่างที่ดี ฉันแก้ไขคำสะกดผิดของคุณ โดยวิธีการจะน่าสนใจถ้าคุณแก้ไขfunctionการยกเว้นfalsyค่า (null, ไม่ได้กำหนด, NaN, '') ...
developer033

8

ใช้ JSON

ลองดูที่คำถามนี้เพื่อดูแนวคิดในการใช้งาน


2
ฉันไม่รู้ว่าเขาเขียนเซิร์ฟเวอร์อะไร แต่ภาษาที่ทันสมัยส่วนใหญ่มีแพ็คเกจที่อ่าน JSON นอกจากนี้แม้ว่าเขาจะใช้งานได้ดีกว่าการใช้โค้ดเซิร์ฟเวอร์อ่าน JSON ดีกว่าสร้างรูปแบบการเข้ารหัสใหม่ของคุณเอง การเข้ารหัส DIY เช่นนี้มีแนวโน้มที่จะเป็นรถ (เพราะโดยปกติคุณจะไม่นึกถึงกรณีที่เป็นไปได้ทั้งหมดเช่นค่าที่เป็นอาร์เรย์ในตัวเอง ฯลฯ ')
Ofri Raviv

คุณแนะนำให้แปลงวัตถุ teh เป็น JSON แล้วส่งสตริง JSON ทั้งหมดไปยังเซิร์ฟเวอร์เป็นพารามิเตอร์การสืบค้น GET เดียวหรือไม่
Marco Demaio

8

ต่อไปนี้เป็นคำตอบที่ยอมรับของรุ่น coffeescript นี่อาจช่วยประหยัดเวลากับใครบางคน

serialize = (obj, prefix) ->
  str = []
  for p, v of obj
    k = if prefix then prefix + "[" + p + "]" else p
    if typeof v == "object"
      str.push(serialize(v, k))
    else
      str.push(encodeURIComponent(k) + "=" + encodeURIComponent(v))

  str.join("&")

ขอบคุณอัลฟองโซ! ประหยัดเวลาของฉันจริงๆ!
ลูคัส

6

นี่คือการกระชับและ recursive รุ่นกับObject.entries มันจัดการอาร์เรย์ที่ซ้อนกันโดยพลการ แต่ไม่วัตถุที่ซ้อนกัน นอกจากนี้ยังลบองค์ประกอบที่ว่างเปล่า:

const format = (k,v) => v !== null ? `${k}=${encodeURIComponent(v)}` : ''

const to_qs = (obj) => {
    return [].concat(...Object.entries(obj)
                       .map(([k,v]) => Array.isArray(v) 
                          ? v.map(arr => to_qs({[k]:arr})) 
                          : format(k,v)))
           .filter(x => x)
           .join('&');
}

เช่น:

let json = { 
    a: [1, 2, 3],
    b: [],              // omit b
    c: 1,
    d: "test&encoding", // uriencode
    e: [[4,5],[6,7]],   // flatten this
    f: null,            // omit nulls
    g: 0
};

let qs = to_qs(json)

=> "a=1&a=2&a=3&c=1&d=test%26encoding&e=4&e=5&e=6&e=7&g=0"

รุ่นนี้ทำงานให้ฉันได้เมื่อต้องจัดการกับอาร์เรย์ที่ซ้อนกัน ปรับแต่งเล็กน้อยเพื่อใช้คีย์อาเรย์ Ruby / PHP แบบ แต่ใช้งานได้ดี
nickb

5

อันนี้ข้ามค่า null / undefined

export function urlEncodeQueryParams(data) {
    const params = Object.keys(data).map(key => data[key] ? `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}` : '');
    return params.filter(value => !!value).join('&');
}

5

ใน ES7 คุณสามารถเขียนสิ่งนี้ในหนึ่งบรรทัด:

const serialize = (obj) => (Object.entries(obj).map(i => [i[0], encodeURIComponent(i[1])].join('=')).join('&'))

4

บรรทัดเดียวเพื่อแปลง Object ให้เป็น Query String ในกรณีที่มีคนต้องการอีกครั้ง

let Objs = { a: 'obejct-a', b: 'object-b' }

Object.keys(objs).map(key => key + '=' + objs[key]).join('&')

// result will be a=object-a&b=object-b

4

ฉันมีวิธีที่ง่ายกว่าที่ไม่ได้ใช้ห้องสมุดบุคคลที่สามใด ๆ และมีแนวโน้มที่จะใช้ในเบราว์เซอร์ใด ๆ ที่มี "Object.keys" (หรือเบราว์เซอร์สมัยใหม่ทั้งหมด + ขอบ + ie):

ใน ES5

function(a){
    if( typeof(a) !== 'object' ) 
        return '';
    return `?${Object.keys(a).map(k=>`${k}=${a[k]}`).join('&')}`;
}

ใน ES3

function(a){
    if( typeof(a) !== 'object' ) 
        return '';
    return '?' + Object.keys(a).map(function(k){ return k + '=' + a[k] }).join('&');
}

3

หากคุณต้องการแปลงวัตถุที่ซ้อนกันซ้ำและวัตถุอาจมีหรือไม่มีอาเรย์ (และอาร์เรย์อาจมีออบเจ็กต์หรืออาร์เรย์ ฯลฯ ) วิธีการแก้ปัญหาก็ซับซ้อนกว่าเล็กน้อย นี่คือความพยายามของฉัน

ฉันได้เพิ่มตัวเลือกบางอย่างเพื่อเลือกถ้าคุณต้องการบันทึกสำหรับสมาชิกแต่ละวัตถุที่ความลึกของวัตถุหลักที่ตั้งอยู่และเพื่อเลือกว่าคุณต้องการเพิ่มป้ายกำกับให้กับสมาชิกที่มาจากอาร์เรย์ที่แปลงแล้วหรือไม่

เป็นการดีที่คุณควรทดสอบว่าสิ่งพารามิเตอร์ได้รับวัตถุหรืออาร์เรย์

function thingToString(thing,maxDepth,recordLevel,markArrays){
    //thing: object or array to be recursively serialized
    //maxDepth (int or false):
    // (int) how deep to go with converting objects/arrays within objs/arrays
    // (false) no limit to recursive objects/arrays within objects/arrays
    //recordLevel (boolean):
    //  true - insert "(level 1)" before transcript of members at level one (etc)
    //  false - just 
    //markArrays (boolean):
    //  insert text to indicate any members that came from arrays
    var result = "";
    if (maxDepth !== false && typeof maxDepth != 'number') {maxDepth = 3;}
    var runningDepth = 0;//Keeps track how deep we're into recursion

    //First prepare the function, so that it can call itself recursively
    function serializeAnything(thing){
        //Set path-finder values
        runningDepth += 1;
        if(recordLevel){result += "(level " + runningDepth + ")";}

        //First convert any arrays to object so they can be processed
        if (thing instanceof Array){
            var realObj = {};var key;
            if (markArrays) {realObj['type'] = "converted array";}
            for (var i = 0;i < thing.length;i++){
                if (markArrays) {key = "a" + i;} else {key = i;}
                realObj[key] = thing[i];
            }
            thing = realObj;
            console.log('converted one array to ' + typeof realObj);
            console.log(thing);
        }

        //Then deal with it
        for (var member in thing){
            if (typeof thing[member] == 'object' && runningDepth < maxDepth){
                serializeAnything(thing[member]);
                //When a sub-object/array is serialized, it will add one to
                //running depth. But when we continue to this object/array's
                //next sibling, the level must go back up by one
                runningDepth -= 1;
            } else if (maxDepth !== false && runningDepth >= maxDepth) {
                console.log('Reached bottom');
            } else 
            if (
                typeof thing[member] == "string" || 
                typeof thing[member] == 'boolean' ||
                typeof thing[member] == 'number'
            ){
                result += "(" + member + ": " + thing[member] + ") ";
            }  else {
                result += "(" + member + ": [" + typeof thing[member] + " not supported]) ";
            }
        }
    }
    //Actually kick off the serialization
    serializeAnything(thing);

    return result;

}

ขอบคุณสำหรับแนวทางแบบเรียกซ้ำ
Sherlock

3

นอกจากนี้สำหรับวิธีการแก้ปัญหาที่ยอมรับซึ่งใช้งานได้กับวัตถุ & อาร์เรย์ของวัตถุ:

parseJsonAsQueryString = function (obj, prefix, objName) {
    var str = [];
    for (var p in obj) {
        if (obj.hasOwnProperty(p)) {
            var v = obj[p];
            if (typeof v == "object") {
                var k = (objName ? objName + '.' : '') + (prefix ? prefix + "[" + p + "]" : p);
                str.push(parseJsonAsQueryString(v, k));
            } else {
                var k = (objName ? objName + '.' : '') + (prefix ? prefix + '.' + p : p);
                str.push(encodeURIComponent(k) + "=" + encodeURIComponent(v));
                //str.push(k + "=" + v);
            }
        }
    }
    return str.join("&");
}

นอกจากนี้ยังได้เพิ่ม objName หากคุณใช้พารามิเตอร์วัตถุเช่นในวิธีการดำเนินการ asp.net mvc


3

ดูดีขึ้นเล็กน้อย

objectToQueryString(obj, prefix) {
    return Object.keys(obj).map(objKey => {
        if (obj.hasOwnProperty(objKey)) {
            const key = prefix ? `${prefix}[${objKey}]` : objKey;
            const value = obj[objKey];

            return typeof value === "object" ?
                this.objectToQueryString(value, key) :
                `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
        }

        return null;
    }).join("&");
}

3

ฉันทำการเปรียบเทียบตัวแยกสตริง JSONและผลลัพธ์มีดังนี้:

JSON:    {"_id":"5973782bdb9a930533b05cb2","isActive":true,"balance":"$1,446.35","age":32,"name":"Logan Keller","email":"logankeller@artiq.com","phone":"+1 (952) 533-2258","friends":[{"id":0,"name":"Colon Salazar"},{"id":1,"name":"French Mcneil"},{"id":2,"name":"Carol Martin"}],"favoriteFruit":"banana"}
Rison:   (_id:'5973782bdb9a930533b05cb2',age:32,balance:'$1,446.35',email:'logankeller@artiq.com',favoriteFruit:banana,friends:!((id:0,name:'Colon Salazar'),(id:1,name:'French Mcneil'),(id:2,name:'Carol Martin')),isActive:!t,name:'Logan Keller',phone:'+1 (952) 533-2258')
O-Rison: _id:'5973782bdb9a930533b05cb2',age:32,balance:'$1,446.35',email:'logankeller@artiq.com',favoriteFruit:banana,friends:!((id:0,name:'Colon Salazar'),(id:1,name:'French Mcneil'),(id:2,name:'Carol Martin')),isActive:!t,name:'Logan Keller',phone:'+1 (952) 533-2258'
JSURL:   ~(_id~'5973782bdb9a930533b05cb2~isActive~true~balance~'!1*2c446.35~age~32~name~'Logan*20Keller~email~'logankeller*40artiq.com~phone~'*2b1*20*28952*29*20533-2258~friends~(~(id~0~name~'Colon*20Salazar)~(id~1~name~'French*20Mcneil)~(id~2~name~'Carol*20Martin))~favoriteFruit~'banana)
QS:      _id=5973782bdb9a930533b05cb2&isActive=true&balance=$1,446.35&age=32&name=Logan Keller&email=logankeller@artiq.com&phone=+1 (952) 533-2258&friends[0][id]=0&friends[0][name]=Colon Salazar&friends[1][id]=1&friends[1][name]=French Mcneil&friends[2][id]=2&friends[2][name]=Carol Martin&favoriteFruit=banana
URLON:   $_id=5973782bdb9a930533b05cb2&isActive:true&balance=$1,446.35&age:32&name=Logan%20Keller&email=logankeller@artiq.com&phone=+1%20(952)%20533-2258&friends@$id:0&name=Colon%20Salazar;&$id:1&name=French%20Mcneil;&$id:2&name=Carol%20Martin;;&favoriteFruit=banana
QS-JSON: isActive=true&balance=%241%2C446.35&age=32&name=Logan+Keller&email=logankeller%40artiq.com&phone=%2B1+(952)+533-2258&friends(0).id=0&friends(0).name=Colon+Salazar&friends(1).id=1&friends(1).name=French+Mcneil&friends(2).id=2&friends(2).name=Carol+Martin&favoriteFruit=banana

ที่สั้นที่สุดในหมู่พวกเขาเป็นURL Object สัญลักษณ์


2

ตกลงมันเป็นโพสต์เก่า แต่ฉันประสบปัญหานี้และฉันได้พบวิธีแก้ปัญหาส่วนตัวของฉัน .. อาจช่วยคนอื่น ..

     function objToQueryString(obj){
        var k = Object.keys(obj);
        var s = "";
        for(var i=0;i<k.length;i++) {
            s += k[i] + "=" + encodeURIComponent(obj[k[i]]);
            if (i != k.length -1) s += "&";
        }
        return s;
     };

2

คำตอบดังกล่าวข้างต้นไม่สามารถใช้งานได้หากคุณมีวัตถุซ้อนอยู่จำนวนมาก คุณสามารถเลือกฟังก์ชั่นพารามิเตอร์ได้จากที่นี่ - https://github.com/knowledgecode/jquery-param/blob/master/jquery-param.js มันทำงานได้ดีมากสำหรับฉัน!

    var param = function (a) {
    var s = [], rbracket = /\[\]$/,
        isArray = function (obj) {
            return Object.prototype.toString.call(obj) === '[object Array]';
        }, add = function (k, v) {
            v = typeof v === 'function' ? v() : v === null ? '' : v === undefined ? '' : v;
            s[s.length] = encodeURIComponent(k) + '=' + encodeURIComponent(v);
        }, buildParams = function (prefix, obj) {
            var i, len, key;

            if (prefix) {
                if (isArray(obj)) {
                    for (i = 0, len = obj.length; i < len; i++) {
                        if (rbracket.test(prefix)) {
                            add(prefix, obj[i]);
                        } else {
                            buildParams(prefix + '[' + (typeof obj[i] === 'object' ? i : '') + ']', obj[i]);
                        }
                    }
                } else if (obj && String(obj) === '[object Object]') {
                    for (key in obj) {
                        buildParams(prefix + '[' + key + ']', obj[key]);
                    }
                } else {
                    add(prefix, obj);
                }
            } else if (isArray(obj)) {
                for (i = 0, len = obj.length; i < len; i++) {
                    add(obj[i].name, obj[i].value);
                }
            } else {
                for (key in obj) {
                    buildParams(key, obj[key]);
                }
            }
            return s;
        };

    return buildParams('', a).join('&').replace(/%20/g, '+');
};

2

ES6 โซลูชั่นสำหรับการเข้ารหัสสตริงแบบสอบถามของวัตถุ JAVASCRIPT

const params = {
  a: 1,
  b: 'query stringify',
  c: null,
  d: undefined,
  f: '',
  g: { foo: 1, bar: 2 },
  h: ['Winterfell', 'Westeros', 'Braavos'],
  i: { first: { second: { third: 3 }}}
}

static toQueryString(params = {}, prefix) {
  const query = Object.keys(params).map((k) => {
    let key = k;
    const value = params[key];

    if (!value && (value === null || value === undefined || isNaN(value))) {
      value = '';
    }

    switch (params.constructor) {
      case Array:
        key = `${prefix}[]`;
        break;
      case Object:
        key = (prefix ? `${prefix}[${key}]` : key);
        break;
    }

    if (typeof value === 'object') {
      return this.toQueryString(value, key); // for nested objects
    }

    return `${key}=${encodeURIComponent(value)}`;
  });

  return query.join('&');
}

toQueryString (params)

"a=1&b=query%20stringify&c=&d=&f=&g[foo]=1&g[bar]=2&h[]=Winterfell&h[]=Westeros&h[]=Braavos&i[first][second][third]=3"

2

นี่คือโซลูชันที่จะใช้งานกับ. NET แบ็กเอนด์ออกจากกล่อง ฉันได้รับคำตอบหลักของกระทู้นี้และปรับปรุงให้เหมาะสมกับ. NET ของเราต้องการ

function objectToQuerystring(params) {
var result = '';

    function convertJsonToQueryString(data, progress, name) {
        name = name || '';
        progress = progress || '';
        if (typeof data === 'object') {
            Object.keys(data).forEach(function (key) {
                var value = data[key];
                if (name == '') {
                    convertJsonToQueryString(value, progress, key);
                } else {
                    if (isNaN(parseInt(key))) {
                        convertJsonToQueryString(value, progress, name + '.' + key);
                    } else {
                        convertJsonToQueryString(value, progress, name + '[' + key+ ']');
                    }
                }
            })
        } else {
            result = result ? result.concat('&') : result.concat('?');
            result = result.concat(`${name}=${data}`);
        }
    }

    convertJsonToQueryString(params);
    return result;
}

1

ฉันเขียนแพคเกจสำหรับสิ่งนั้น: object-query-string :)

รองรับวัตถุที่ซ้อนกันอาร์เรย์ฟังก์ชั่นการเข้ารหัสที่กำหนดเอง ฯลฯ มีน้ำหนักเบา & jQuery ฟรี

// TypeScript
import { queryString } from 'object-query-string';

// Node.js
const { queryString } = require("object-query-string");

const query = queryString({
    filter: {
        brands: ["Audi"],
        models: ["A4", "A6", "A8"],
        accidentFree: true
    },
    sort: 'mileage'
});

ผลตอบแทน

filter[brands][]=Audi&filter[models][]=A4&filter[models][]=A6&filter[models][]=A8&filter[accidentFree]=true&sort=milage

0

อีกวิธีหนึ่ง (ไม่มีวัตถุแบบเรียกซ้ำ):

   getQueryString = function(obj)
   {
      result = "";

      for(param in obj)
         result += ( encodeURIComponent(param) + '=' + encodeURIComponent(obj[param]) + '&' );

      if(result) //it's not empty string when at least one key/value pair was added. In such case we need to remove the last '&' char
         result = result.substr(0, result.length - 1); //If length is zero or negative, substr returns an empty string [ref. http://msdn.microsoft.com/en-us/library/0esxc5wy(v=VS.85).aspx]

      return result;
   }

alert( getQueryString({foo: "hi there", bar: 123, quux: 2 }) );

0

อ้างถึงจากคำตอบ @ user187291 เพิ่ม "isArray" เป็นพารามิเตอร์เพื่อให้อาร์เรย์ json ซ้อนกันที่จะถูกแปลง

data : {
                    staffId : "00000001",
                    Detail : [ {
                        "identityId" : "123456"
                    }, {
                        "identityId" : "654321"
                    } ],

                }

ในการสร้างผลลัพธ์:

staffId = 00000001 & รายละเอียด [0] .identityId = 123456 & รายละเอียด [1] .identityId = 654321

serialize = function(obj, prefix, isArray) {
        var str = [],p = 0;
        for (p in obj) {
            if (obj.hasOwnProperty(p)) {
                var k, v;
                if (isArray)
                    k = prefix ? prefix + "[" + p + "]" : p, v = obj[p];
                else
                    k = prefix ? prefix + "." + p + "" : p, v = obj[p];

                if (v !== null && typeof v === "object") {
                    if (Array.isArray(v)) {
                        serialize(v, k, true);
                    } else {
                        serialize(v, k, false);
                    }
                } else {
                    var query = k + "=" + v;
                    str.push(query);
                }
            }
        }
        return str.join("&");
    };

    serialize(data, "prefix", false);

0

นอกจากนี้คุณยังสามารถบรรลุนี้โดยใช้ง่ายJavaScript

const stringData = '?name=Nikhil&surname=Mahirrao&age=30';
    
const newData= {};
stringData.replace('?', '').split('&').map((value) => {
  const temp = value.split('=');
  newData[temp[0]] = temp[1];
});

console.log('stringData: '+stringData);
console.log('newData: ');
console.log(newData);


1
นี่คือการออกกำลังกายที่ดี แต่นี่เป็นวิธีอื่น ๆ ไม่ใช่คำตอบสำหรับคำถาม
Christiaan Westerbeek
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.