Kodowanie ciągu znaków zapytania obiektu JavaScript

481

Czy znasz szybki i prosty sposób na zakodowanie obiektu JavaScript w obiekcie, stringktóry mogę przekazać za pośrednictwem GETżądania?

Nie jQuery, żadnych innych frameworków - po prostu Javascript :)

napolux
źródło
Dlaczego JQuery nie może być rozwiązaniem, jeśli istnieje odpowiednie rozwiązanie?
eaglei22
@ eaglei22, ponieważ w tym czasie pracowałem nad projektem urządzenia set-box IPTV i żadne biblioteki zewnętrzne nie były dozwolone. ;-)
napolux
1
Dzięki za odpowiedzi. Od czasu do czasu widzę tę specyfikację i zawsze zastanawiałem się, dlaczego tak się dzieje. Cóż, teraz mam jeden, dzięki! :)
eaglei22
9
@ eaglei22 Ponieważ czasami nie chcesz ładować dużej biblioteki, aby uzyskać jeden element według identyfikatora.
Aaron Harun
większość przeglądarek obsługuje URLSearchParamsteraz ...
mb21

Odpowiedzi:

810

lubię to?

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

Edycja: ten konwertuje również obiekty rekurencyjne (używając notacji php „tablica” dla ciągu zapytania)

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

187291
źródło
2
Czy to nie złamie, biorąc pod uwagę {foo: [1,2,3], takt: "100%"}?
Quentin,
1
@Ofri: W przypadku żądań POST do serwera skonfigurowanego do odbierania JSON jest dobrym wyborem. W przypadku żądań GET, jeśli wysyłasz na serwer cokolwiek innego niż kilka prostych parametrów, prawdopodobnie projekt jest nieprawidłowy.
Tim Down
2
@Marcel To dlatego, że funkcja nie sprawdza hasOwnProperty. Zaktualizowałem twoje skrzypce, więc teraz robi to: jsfiddle.net/rudiedirkx/U5Tyb/1
Rudie
1
@TimDown Odnośnie komentarza wysyłanie prostych parametrów w żądaniach GET. Nie zgadzam się. Grupowanie parametrów w tablice może się przydać, gdy PHP po stronie serwera znajdzie gotową stabilną tablicę asocjacyjną. Nie rozumiem, dlaczego jest to zły projekt.
Savas Vedova
1
Czy „if (obj.hasOwnProperty (prop))” jest konieczne? Pętla instrukcji in in tuż nad właściwościami obiektu, dlatego wywołanie hasOwnProperty zawsze ma wartość true
Arnon
231

jQuery ma do tego funkcję jQuery.param(), jeśli już go używasz, możesz go użyć: http://api.jquery.com/jquery.param/

przykład:

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

str teraz zawiera width=1680&height=1050

Benvds
źródło
119
cytując Napolux (OP): „zwykły Javascript” . : P
Sk8erPeter,
6
jQuery.param () ma złowrogie zachowanie. Spróbuj wykonać var ​​a = []; a [2564] = 12; console.log (jQuery.param ({lista właściwości: a})); żeby zobaczyć o co mi chodzi.
akond
13
@akond Dokumentacja jQuery wyraźnie mówi, że nie możesz przekazać pustej tablicy.
Ariel
4
@Ariel Nie przechodzi w pustej tablicy. Przechodzi w tablicy z tylko jedną wartością o indeksie 2564. Aby zademonstrować: var a = []; a[5] = 'foo'; jQuery.param({ parameters: a }); Wyniki w "parameters[]=&parameters[]=&parameters[]=&parameters[]=&parameters[]=&parameters[]=foo". Które, choć poprawne, może nie być tym, czego oczekujesz.
Chris Hall
4
Pytanie konkretnie zadał Vanilla JS
Bug Hunter 219
188

Wystarczy użyć URLSearchParamsTo działa we wszystkich obecnych przeglądarkach

new URLSearchParams(object).toString()
nullaber
źródło
5
Nie, ponieważ nie robi obiektów rekurencyjnych
Eddie Monge Jr
Nie działa na zagnieżdżonym obiekcie. let j = { m: 5, n: { k: 1 } }; new URLSearchParams(j).toString(); // result "m=5&n=%5Bobject+Object%5D"
hitautodestruct
19
@EddieMongeJr Ciągi zapytań są z założenia parami klucz-wartość, nie powinieneś nawet chcieć serializować zagnieżdżonych obiektów Ta odpowiedź jest nowoczesną drogą. Potrzebne głosy poparcia.
Romain Durand,
5
Tak, są to pary klucz-wartość, ale nic nie mówi, że wartość nie może być obiektem zakodowanym w postaci ciągu. Ponadto w oryginalnych pytaniach prosi się o „obiekt JavaScript w łańcuch”, który może mieć właściwości zagnieżdżone
Eddie Monge Jr
@EddieMongeJr nawet zaakceptowana odpowiedź (i inne po krótkim spojrzeniu) nie obsługuje zagnieżdżonego obiektu. Możesz stringifyzagnieżdżone obiekty, zanim będziesz mógłURLSearchParams
Mosh Feu
128
Object.keys(obj).reduce(function(a,k){a.push(k+'='+encodeURIComponent(obj[k]));return a},[]).join('&')

Edycja: Podoba mi się ten linijka, ale założę się, że byłaby bardziej popularna, gdyby pasowała do zaakceptowanej odpowiedzi semantycznie:

function serialize( obj ) {
    let str = '?' + Object.keys(obj).reduce(function(a, k){
        a.push(k + '=' + encodeURIComponent(obj[k]));
        return a;
    }, []).join('&');
    return str;
}
sergk
źródło
1
Jednak dedykowana linia dla funkcji redukcji znacznie poprawiłaby czytelność.
Aurelien Ribon,
54
Użycie .map () zamiast .reduce () byłoby jeszcze prostsze: Object.keys(obj).map(k => k + '=' + encodeURIComponent(obj[k])).join('&')
Jannes
2
Należy zauważyć, że Object.keysjest dostępna tylko w IE> = 9
Johnston
5
Dalsza poprawa kodu @Jannes za pomocą szablonów ES6 zamiast konkatenacji -Object.keys(obj).map(k => `${k}=${encodeURIComponent(obj[k])}`).join('&')
csilk
1
Jeśli twoje klucze również wymagają kodowaniaUriComponent ❤️: Object.entries(obj).map(e => e.map(ee => encodeURIComponent(ee)).join('=')).join('&');
Blaise,
112

Oto jedna linijka w ES6:

Object.keys(obj).map(k => `${encodeURIComponent(k)}=${encodeURIComponent(obj[k])}`).join('&');
Nico Tejera
źródło
zamień klucz w / k i jesteś złoty
Jamie Kudla
17
Ostrzeżenie! Działa to tylko na płytkich obiektach. Jeśli masz właściwość najwyższego poziomu, która jest innym obiektem, ta jedna linijka wyświetli „klucz =% 5Bobject% 20Object% 5D”. Tak jak heads up.
Andrew Allbright,
4
Nie pluje to również tablic. Mam pojęcie, export?actions[]=finance,create,editkiedy powinno mieć export?actions[]=finance&actions[]=create&actions[]=edittak okropny standard.
darkbluesun
3
Tablice są prawie zawsze „na własną rękę”, ponieważ argumenty URL są tylko ciągami, jeśli chodzi o specyfikację, więc masz problem, aby wszystko, co nie jest pojedynczym ciągiem, zostało poprawnie odczytane przez serwer dzwonisz. actions[]jest notacją PHP; Django actionzamiast tego używa wielu (bez []przyrostka); niektóre inne ORM / CMS wymagają list oddzielonych przecinkami itp. Więc „jeśli to nie są proste ciągi, najpierw upewnij się, że wiesz, czego Twój serwer nawet chce”.
Mike 'Pomax' Kamermans
Bardzo eleganckie rozwiązanie!
Anh Tran
51

Z Node.js v6.6.3

const querystring = require('querystring')

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

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

Odniesienie: https://nodejs.org/api/querystring.html

Lucas Constantino Silva
źródło
8
To nie powinno być odrzucone IMO, jeśli to JS na serwerze, to powinna być poprawna odpowiedź.
Michael Benin,
4
Wygląda na to, że nie obsługuje zagnieżdżonych obiektów.
Yarin Gold
43

Sugeruję użycie URLSearchParamsinterfejsu:

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())

Lub przekazując obiekt wyszukiwania do konstruktora w następujący sposób:

const obj = {foo: "hi there", bar: "100%" };
const params = new URLSearchParams(obj).toString();
bmaggi
źródło
1
Ciekawa sugestia, ale należy pamiętać, że obsługa tej funkcji w przeglądarce jest nadal bardzo niejednolita.
mrec
Jeśli nie będziesz obsługiwać IE (który jest obecnie dość powszechny) i niektórych konkretnych wersji mobilnych, jest to najlepsza odpowiedź, ponieważ jest to zwykły JavaScript.
Marcos Sandrini
24

Mała poprawka do zaakceptowanego rozwiązania przez użytkownika187291:

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

Sprawdzanie hasOwnProperty na obiekcie sprawia, że ​​JSLint / JSHint jest szczęśliwy i zapobiega przypadkowemu szeregowaniu metod obiektu lub innych rzeczy, jeśli obiekt jest czymś innym niż zwykłym słownikiem. Patrz akapit na oświadczenia na tej stronie: http://javascript.crockford.com/code.html

jssebastian
źródło
14

Wygląda na to, że wszyscy wkładają tu swoją liniówkę, więc oto moja:

const encoded = Object.entries(obj).map(([k, v]) => `${k}=${encodeURIComponent(v)}`).join("&");
Alex Escalante
źródło
1
Object.entries nie jest obsługiwany w IE.
MBouwman,
@MBouwman oczywiście, IE jest złamane poza dobrem i złem, dlatego musisz używać babel / core-js
chpio
@chpio Babel / core-js nie obsługuje Object.entries, jeśli mam rację.
MBouwman,
rdzeń ma obsługę Object.entries: github.com/zloirock/core-js/blob/master/… i nawet stara transformacja środowiska uruchomieniowego babel corejs2 obsługuje go również github.com/babel/babel/blob/...
chpio
12

Czy musisz wysyłać dowolne obiekty? Jeśli tak, GET jest złym pomysłem, ponieważ istnieją ograniczenia długości adresów URL, które akceptują agenci użytkownika i serwery WWW. Moją sugestią byłoby zbudowanie tablicy par nazwa-wartość do wysłania, a następnie utworzenie ciągu zapytania:

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() );
Tim Down
źródło
11

Kreator zapytań w stylu Rails / PHP

Ta metoda przekształca obiekt Javascript w plik URI Query String. Obsługuje również zagnieżdżone tablice i obiekty (w Rails/ PHPsyntax):

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('&');
}

Przykładowe użycie:

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
Sheharyar
źródło
Niezły przykład. Poprawiłem literówkę w twojej odpowiedzi. Nawiasem mówiąc, byłoby interesujące, jeśli edytujesz swoje, functionaby wykluczyć falsywartości (null, undefined, NaN, '') ...
developer033
8

użyj JSON.

spójrz na to pytanie, aby znaleźć pomysły na wdrożenie.

Ofri Raviv
źródło
2
Nie wiem, w czym pisze serwer, ale większość współczesnych języków ma dobre pakiety, które czytają JSON. Poza tym, nawet jeśli ostatecznie go wdroży, lepiej zaimplementować kod serwera czytającego JSON, niż wymyślić własny własny schemat kodowania. Takie kodowanie DIY może być błędne (ponieważ zazwyczaj nie myślisz o wszystkich możliwych przypadkach, takich jak wartość sama w sobie itp.).
Ofri Raviv
czy w zasadzie sugerujesz konwersję obiektu na JSON, a następnie przekazanie całego łańcucha JSON na serwer jako pojedynczy parametr zapytania GET?
Marco Demaio,
8

Oto coffeescriptowa wersja zaakceptowanej odpowiedzi. Może to komuś zaoszczędzić czas.

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("&")
alf
źródło
Dzięki alfonso! Naprawdę zaoszczędziłem czas!
Lukas
6

Oto zwięzła i rekurencyjna wersja z Object.entries . Obsługuje dowolnie zagnieżdżone tablice, ale nie zagnieżdżone obiekty. Usuwa również puste elementy:

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('&');
}

Na przykład:

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"
mikebridge
źródło
Ta wersja wykonała dla mnie zadanie w przypadku tablic zagnieżdżonych. Wprowadzono drobną modyfikację, aby używać kluczy tablicowych w stylu Ruby / PHP, ale poza tym działa świetnie.
nickb
5

Ta pomija wartości zerowe / niezdefiniowane

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

W ES7 możesz napisać to w jednym wierszu:

const serialize = (obj) => (Object.entries(obj).map(i => [i[0], encodeURIComponent(i[1])].join('=')).join('&'))
Pavlo Sadovyi
źródło
4

Pojedyncza linia do konwersji obiektu na ciąg zapytania, na wypadek, gdyby ktoś go ponownie potrzebował

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
Laravel Plus
źródło
4

Mam prostsze rozwiązanie, które nie korzysta z żadnej biblioteki innej firmy i jest już gotowe do użycia w dowolnej przeglądarce, która ma „Object.keys” (inaczej wszystkie współczesne przeglądarki + Edge + ie):

W ES5

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

W ES3

function(a){
    if( typeof(a) !== 'object' ) 
        return '';
    return '?' + Object.keys(a).map(function(k){ return k + '=' + a[k] }).join('&');
}
LeandroLuk
źródło
3

Jeśli chcesz rekurencyjnie przekonwertować zagnieżdżony obiekt, a obiekt może zawierać tablice lub nie (a tablice mogą zawierać obiekty lub tablice itp.), Rozwiązanie staje się nieco bardziej złożone. To jest moja próba.

Dodałem również kilka opcji do wyboru, jeśli chcesz nagrywać dla każdego elementu obiektu na jakiej głębokości w głównym obiekcie, w którym on się znajduje, oraz do wyboru, czy chcesz dodać etykietę do elementów pochodzących z przekonwertowanych tablic.

Idealnie powinieneś przetestować, czy parametr rzeczy rzeczywiście otrzymuje obiekt lub tablicę.

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;

}
Wytze
źródło
Dzięki za rekurencyjne podejście
Sherlock,
3

Dodanie do zaakceptowanego rozwiązania, działa z obiektami i tablicą obiektów:

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("&");
}

Dodano także obiekt objName, jeśli używasz parametrów obiektu, takich jak metody akcji asp.net mvc.

A.Aziem Moemen
źródło
3

Trochę lepiej wyglądają

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("&");
}
Pavel
źródło
3

Zrobiłem porównanie stringifiers JSON , a wyniki przedstawiają się następująco:

JSON:    {"_id":"5973782bdb9a930533b05cb2","isActive":true,"balance":"$1,446.35","age":32,"name":"Logan Keller","email":"[email protected]","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:'[email protected]',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:'[email protected]',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

Najkrótsza z nich to notacja obiektowa adresu URL .

niutech
źródło
2

ok, to starszy post, ale mam do czynienia z tym problemem i znalazłem swoje osobiste rozwiązanie ... może może pomóc komuś innemu ...

     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;
     };
hayatoShingu
źródło
2

Powyższe odpowiedzi nie działają, jeśli masz wiele zagnieżdżonych obiektów. Zamiast tego możesz wybrać parametr funkcji tutaj - https://github.com/knowledgecode/jquery-param/blob/master/jquery-param.js Działa to dla mnie bardzo dobrze!

    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, '+');
};
Vandana Sharma
źródło
2

ES6 ROZWIĄZANIE DO ZAPYTANIA STRINGOWEGO KODOWANIA OBIEKTU 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 (parametry)

"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"
gandharv garg
źródło
2

To rozwiązanie będzie działać dla backendów .NET od razu po wyjęciu z pudełka. Wziąłem podstawową odpowiedź tego wątku i zaktualizowałem go, aby pasował do naszych potrzeb .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;
}
Angel Venchev
źródło
1

Napisałem właśnie do tego pakiet: object-query-string :)

Obsługuje zagnieżdżone obiekty, tablice, niestandardowe funkcje kodowania itp. Lekki i bez 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'
});

zwroty

filter[brands][]=Audi&filter[models][]=A4&filter[models][]=A6&filter[models][]=A8&filter[accidentFree]=true&sort=milage
dayvee.cz
źródło
0

Po prostu inny sposób (brak obiektu rekurencyjnego):

   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 }) );
Marco Demaio
źródło
0

Zapoznaj się z odpowiedzią @ user187291, dodaj „isArray” jako parametr, aby konwertować zagnieżdżoną tablicę json.

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

                }

Aby uzyskać wynik:

staffId = 00000001 i Szczegół [0] .identityId = 123456 i Szczegół [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);
Długi Łowca
źródło
0

Możesz to również osiągnąć za pomocą prostego 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);

Nikhil Mahirrao
źródło
1
To miłe ćwiczenie, ale jest na odwrót. Brak odpowiedzi na pytanie.
Christiaan Westerbeek,