2017-04-26 179 views
0

我需要幫助解決jQuery的$ .param()缺乏足夠深的問題,並且它會留下一些深度的JSON,例如%5D等等。將Javascript對象或jQuery對象轉換爲查詢字符串

不,這是一個PayEezy電子商務API的事情,但他們的沙盒API需要一個查詢字符串,如下所示:

https://api-cert.payeezy.com/v1/securitytokens?apikey=FAKEZdp9nJrKu46wX9evGNnRbGL38W6I&js_security_key=js-FAKE79a767d3fea1611ae66e1c6bfd2af8f879a767d3fea1&callback=respondPEZ&auth=true&ta_token=NOIW&type=FDToken&currency=USD&credit_card.cardholder_name=John+Doe&credit_card.card_number=4111111111111111&credit_card.exp_date=1218&credit_card.cvv=100&credit_card.type=visa&billing_address.street=&billing_address.city=&billing_address.state_province=&billing_address.zip_postal_code=&billing_address.country=&billing_address.email=&billing_address.phone.type=&billing_address.phone.number=

正如你看,我希望你能注意到的東西像billing_address.state而不是billing_address[state],而不是billing_address%5Bstate%5D。我需要PayEezy的一種特殊方式。

所以,我創建在Javascript這個JSON對象,像這樣:

var o = { 
    apikey: 'FAKEZdp9nJrKu46wX9evGNnRbGL38W6I', 
    js_security_key: 'js-FAKE79a767d3fea1611ae66e1c6bfd2af8f879a767d3fea1', 
    callback: 'respondPEZ', 
    auth: true, 
    ta_token: 'NOIW', 
    type: 'FDToken', 
    currency: 'USD',     
    credit_card: { 
     type: 'visa', 
     cardholder_name: 'John Doe', 
     card_number: '4111111111111111', 
     exp_date: '1218', 
     cvv: '100' 
    }, 
    billing_address: { 
     street: undefined, 
     city: undefined, 
     state_province: undefined, 
     zip_postal_code: undefined, 
     country: undefined, 
     email: undefined, 
     phone: { 
      type: undefined, 
      number: undefined 
     } 
    } 
}; 

現在,當您運行通過jQuery的$ .PARAM(),你這不是在查詢字符串足夠接近的結果:

apikey=FAKEZdp9nJrKu46wX9evGNnRbGL38W6I&js_security_key=js-FAKE79a767d3fea1611ae66e1c6bfd2af8f879a767d3fea1&callback=respondPEZ&auth=true&ta_token=NOIW&type=FDToken&currency=USD&credit_card%5Btype%5D=visa&credit_card%5Bcardholder_name%5D=John+Doe&credit_card%5Bcard_number%5D=4111111111111111&credit_card%5Bexp_date%5D=12%2F18&credit_card%5Bcvv%5D=100&billing_address%5Bstreet%5D=&billing_address%5Bcity%5D=&billing_address%5Bstate_province%5D=&billing_address%5Bzip_postal_code%5D=&billing_address%5Bcountry%5D=&billing_address%5Bemail%5D=&billing_address%5Bphone%5D%5Btype%5D=&billing_address%5Bphone%5D%5Bnumber%5D=

看到那些%5D%5B?這些是不受歡迎的,而不是PayEezy在他們的API中想要的。

所以,我設法接近通過這樣做解決了這個問題:

var s = decodeURIComponent($.param(o,false)); 

但後來發現,我可以更通過這樣修正:

var s = decodeURIComponent($.param(o,false)) 
    .replace(/\]\=/g,'=') 
    .replace(/\]\[/g,'.') 
    .replace(/\[/g,'.'); 

我對你的問題是 - 是否有一種更加優化的方式來將嵌入對象的JSON對象轉換爲更友好的URL查詢字符串,該字符串不包括方括號,並且包含點符號,並且可能在比正則表達式更少的代碼行中取代我以前定居的技術?例如,在jQuery或Javascript中是否已經有了一些函數,當它們結合起來處理這個我不知道的很好的東西時呢?

+2

使自己的串行器。 https://github.com/jquery/jquery/blob/master/src/serialize.js –

回答

0

我做了我自己的遞歸序列化器。希望它按要求工作。

該函數將遍歷對象的所有屬性。如果該值是一個對象,它將自行調用並通過"breadcrum"。 A breadcrum只是函數已經到達的位置的「路徑」。例如,如果我們查看帳單郵寄地址中的電話類型,傳遞給該功能的breadcrum將爲billing_address.phone.

如果該值不是一個對象,那麼它只是將自身追加到breadcrum,並將其自身附加到查詢字符串中。

如果值爲undefined,我只是將它設置爲空字符串。

var o = { 
 
    apikey: 'FAKEZdp9nJrKu46wX9evGNnRbGL38W6I', 
 
    js_security_key: 'js-FAKE79a767d3fea1611ae66e1c6bfd2af8f879a767d3fea1', 
 
    callback: 'respondPEZ', 
 
    auth: true, 
 
    ta_token: 'NOIW', 
 
    type: 'FDToken', 
 
    currency: 'USD',     
 
    credit_card: { 
 
     type: 'visa', 
 
     cardholder_name: 'John Doe', 
 
     card_number: '4111111111111111', 
 
     exp_date: '1218', 
 
     cvv: '100' 
 
    }, 
 
    billing_address: { 
 
     street: undefined, 
 
     city: undefined, 
 
     state_province: undefined, 
 
     zip_postal_code: undefined, 
 
     country: undefined, 
 
     email: undefined, 
 
     phone: { 
 
      type: undefined, 
 
      number: undefined 
 
     } 
 
    } 
 
}; 
 

 
function convertToQueryString(object, currentBreadcrum = '') { 
 
    var queryString = ''; 
 
    
 
    for (var property in object) { 
 
     var potentialObject = object[property]; 
 
     
 
     if (typeof potentialObject === 'undefined') { 
 
      potentialObject = ''; 
 
     } // set undefined values to an empty string 
 
     
 
     if (typeof potentialObject === 'object') { 
 
      queryString += convertToQueryString(potentialObject, currentBreadcrum + property + '.'); 
 
     } else { 
 
      if (currentBreadcrum === '' && queryString === '') { // don't prepend an '&' if it's the first item in the query string 
 
       queryString += currentBreadcrum + property + '=' + potentialObject; 
 
      } else { 
 
       queryString += '&' + currentBreadcrum + property + '=' + potentialObject; 
 
      } 
 
     } 
 
    } 
 
    
 
    return queryString; 
 
} 
 

 
console.log(convertToQueryString(o));