Come creare una stringa di query con Javascript


Risposte:


-24

Ho provato a cercare una risposta a questa domanda qualche tempo fa, ma ho finito per scrivere la mia funzione che estrae i valori dal modulo ..

non è perfetto ma si adatta alle mie esigenze.

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 restituisce una mappatura (chiave -> valore) dei parametri. l'input è l'elemento form (elemento DOM)

Non gestisce i campi che consentono la selezione multipla.


44
Sono solo io o non rispondo affatto alla domanda? Stava chiedendo una stringa di query, non un array mappato.
Jake Wilson,

2
@JakeWilson Sì, questa risposta risponde solo a metà della domanda. L'array deve ancora entrare in un formato stringa di query.
Hutch Moore,

9
wow, allora dovevo essere stato un noob in JS. Utilizzo new Array()per inizializzare un dizionario. Ma poi di nuovo, il codice sembra molto più pulito di alcune delle cazzate che scriverei in questi giorni!
hasen

2
@che forse potresti prendere in considerazione la modifica di questa risposta o, um, beh, eliminarla? Ha sempre più voti negativi ogni volta che scorro fino ad esso = MrGreen (ricordo anche il momento in cui aveva un rapporto positivo ...)
Klesun

1
@ArturKlesun sì, no. Non mi interessa. Puoi provare a chiedere alla persona che ha posto la domanda di non accettare questa risposta.
hasen

220

Aggiornamento 2k20: usa la soluzione di Josh con URLSearchParams.toString () .

Vecchia risposta:


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

Per i browser che non supportano la sintassi della funzione freccia che richiede ES5, modificare la .map...riga in

    .map(function(k) {return esc(k) + '=' + esc(params[k]);})

8
La migliore soluzione che abbia mai visto - molto pulita e concisa. Un paio di avvertimenti, però. 1) in .map (), sia k che params [k] devono essere codificati, ad esempio encodeURIComponent (k) e encodeURIComponent (params [k]). 2) È consentito avere più di un'istanza di un parametro denominato in una stringa di query. Se si desidera tale funzionalità, è necessario utilizzare un array anziché un oggetto (la maggior parte delle applicazioni non lo vorrà o non ne avrà bisogno).
John Deighan,

9
3) Non tutti i browser supportano la sintassi della funzione freccia (che richiede ES5). Se si desidera supportare tutti i browser (e codificare le parti), sostituire il precedente .map () con .map (funzione (k) {return encodeURIComponent (k) + '=' + encodeURIComponent (params [k]);})
John Deighan,

1
Bellissimo. Veramente bello.
Mikko Ohtamaa,

9
"non abbastanza jquery"
Eugene Pankov,

1
@ user1738579 Ho modificato la risposta per includere anche il tuo esempio per non-ES5.
Taylor Edmiston,

134

Se stai usando jQuery potresti voler dare un'occhiata a jQuery.param() http://api.jquery.com/jQuery.param/

Esempio:

var params = {
    parameter1: 'value1',
    parameter2: 'value2',
    parameter3: 'value3' 
};
var query = $.param(params);
document.write(query);

13
Questa è in realtà la risposta corretta! La stringa di query per un modulo è $.param($('#myform').serializeArray()).
Jesse

7
@Jesse, quello sarebbe lo stesso risultato di:$('#myform').serialize()
mannaia

95
jQuery !== JavaScript
gphilip,

14
@gphilip Bene, ecco perché ho iniziato la risposta con "Se stai usando jQuery ...". Altrimenti, se si desidera implementarlo in JS vaniglia, è possibile esaminare l'implementazione di jQuery.param()qui github.com/jquery/jquery/blob/master/src/serialize.js :)
Klemen Tušar,

2
A differenza della mia risposta, questa supporta oggetti nidificati comesomeStr=value1&someObj[a]=5&someObj[b]=6&someArr[]=1&someArr[]=2
Klesun,

113

L'API URLSearchParams è disponibile in tutti i browser moderni. Per esempio:

const params = new URLSearchParams({
  var1: "value",
  var2: "value2",
  arr: "foo",
});
console.log(params.toString());
//Prints "var1=value&var2=value2&arr=foo"


3
La migliore risposta qui imo. Solo per aggiungerlo, puoi farlo in params.append(key, value)seguito per aggiungere nuovi parametri di ricerca in scenari più complicati.
Mingwei Zhang,

4
Si noti che i valori indefiniti e nulli sono inclusi nella stringa finale:x=null&y=undefined
pomber

2
Inoltre, se hai già un oggetto URL (ad esempio const url = new URL("https://stackoverflow.com")), puoi impostare le stringhe di query url.search = new URLSearchParams({foo: "bar"})ourl.searchParams.append("foo", "bar")
Miguel Pynto il

Nota che TS avvertirà di usare un oggetto semplice, ma funziona comunque bene
Vadorequest

@pomber Qualche buona idea su come filtrare quegli oggetti non definiti?
Dan Gayle,

53

Questo non risponde direttamente alla tua domanda, ma ecco una funzione generica che creerà un URL che contiene parametri della stringa di query. I parametri (nomi e valori) sono salvati in modo sicuro per l'inclusione in un 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
Esiste una funzione integrata simile a questa in uno dei populari framework javascript come jquery, mootools, ecc ...?
Samuel,

Una più robusta soluzione nativa JavaScript è a stackoverflow.com/a/1714899/1269037
Dan Dascalescu

La più strana implementazione di sempre, perché è necessario inizializzare per un new Arraypo 'quando la usi effettivamente come oggetto? o, O
Umut Sirin,

@UmutSirin Lol sì, non sapevo molto su Javascript al momento. xD Penso che lo stavo trattando come un array PHP. Sentiti libero di refactoring se vuoi.
Michael,

@Michael Haha, sì. Ho appena inviato una modifica. Grazie per la risposta!
Umut Sirin,

22

Con jQuery puoi farlo entro $.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)

Facendo uso di Object.entries(), che restituisce una matrice di [key, value]coppie di oggetti . Ad esempio, perché {a: 1, b: 2}ritornerebbe [['a', 1], ['b', 2]]. Non è supportato (e non lo sarà) solo da IE.

Codice:

const buildURLQuery = obj =>
      Object.entries(obj)
            .map(pair => pair.map(encodeURIComponent).join('='))
            .join('&');

Esempio:

buildURLQuery({name: 'John', gender: 'male'});

Risultato:

"name=John&gender=male"


10

No, non credo che JavaScript standard abbia quello integrato, ma Prototype JS ha quella funzione (sicuramente la maggior parte degli altri framework JS ha anche, ma non li conosco), lo chiamano serializzare .

Posso consigliare Prototype JS, funziona abbastanza bene. L'unico inconveniente che ho notato è che sono le dimensioni (poche centinaia di kb) e l'ambito (un sacco di codice per ajax, dom, ecc.). Quindi, se vuoi solo un serializzatore di moduli è eccessivo, e in senso stretto se vuoi solo la sua funzionalità Ajax (che è principalmente quello per cui l'ho usato) è eccessivo. A meno che tu non stia attento, potresti scoprire che fa un po 'troppo "magia" (come estendere ogni elemento dom che tocca con le funzioni Prototype JS solo per trovare elementi) rallentandolo in casi estremi.


Mi chiedo solo se c'è qualcosa di incorporato. Sembra che ci dovrebbe essere. Odio il prototipo, ma non lo tengo contro di te :)

Quando è stato progettato JavaScript, Ajax non è stato ancora scoperto, quindi analizzare un modulo solo per ottenere la querystring (che si sarebbe creata da solo quando inviato) probabilmente non aveva molto senso. Oggi lo fa, duro ... A proposito, rispetto a script.aculo.us, il prototipo è bello . :)
Stein G. Strindhaug,


6

Se non si desidera utilizzare una libreria, questo dovrebbe coprire la maggior parte / tutti gli stessi tipi di elementi del modulo.

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

Grazie! Stavo affrontando lo stesso problema del poster originale e la tua funzione era esattamente ciò di cui avevo bisogno.
dagw

4

In realtà non è necessario un modulo per farlo con Prototype. Basta usare la funzione 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
Certo, hai risposto quasi 10 anni fa, ma questo codice è ora obsoleto.
SEoF

4

Puoi farlo al giorno d'oggi con FormDatae URLSearchParamssenza la necessità di eseguire il loop su qualsiasi cosa.

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

Tuttavia, i browser più vecchi avranno bisogno di un polyfill.


3

Non sono del tutto sicuro di me stesso, ricordo di aver visto jQuery in una certa misura, ma non gestisce affatto i record gerarchici, figuriamoci in un modo php friendly.

Una cosa che so per certo, è quando si creano URL e si inserisce il prodotto nella dom, non si usa semplicemente la colla per stringhe per farlo, o si aprirà a un pratico interruttore di pagina.

Ad esempio, alcuni software pubblicitari incorporano la stringa della versione da qualunque cosa esegua il tuo flash. Questo va bene quando adotta una semplice stringa generica, ma è comunque molto ingenua e esplode in un disordine imbarazzante per le persone che hanno installato Gnash, poiché la stringa di versione di gnash contiene una licenza di copyright GPL completa, completa di URL e tag <a href>. Usando questo nel tuo generatore di inserzionisti colla-colla, la pagina si spalanca e fa apparire HTML sbilanciato nella dom.

La morale della storia:

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

Non:

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

Google ha bisogno di imparare questo trucco. Ho provato a segnalare il problema, sembrano non curarsene.


Va bene. Document.write è così 1995, comunque.

2

Come dice Stein, è possibile utilizzare la libreria prototipo javascript da http://www.prototypejs.org . Includi il JS ed è molto semplice, $('formName').serialize()ti restituirà quello che vuoi!



2

Potrebbe essere un po 'ridondante, ma il modo più pulito che ho trovato si basa su alcune delle risposte qui:

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,
})

fonte


1

Queste risposte sono molto utili, ma voglio aggiungere un'altra risposta, che potrebbe aiutarti a creare l'URL completo. Questo può aiutare a concat di base url, path, hashe parameters.

var url = buildUrl('http://mywebsite.com', {
        path: 'about',
        hash: 'contact',
        queryParams: {
            'var1': 'value',
            'var2': 'value2',
            'arr[]' : 'foo'
        }
    });
    console.log(url);

È possibile scaricare tramite npm https://www.npmjs.com/package/build-url

demo:

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

So che questa è una risposta molto tardi, ma funziona molto bene ...

var obj = {
a:"a",
b:"b"
}

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

nota: object.entries restituirà chiave, coppie di valori

l'output dalla riga sopra sarà a = a & b = b

Spero che aiuti qualcuno.

Happy Coding ...


0

Probabilmente è troppo tardi per rispondere alla tua domanda.
Ho avuto la stessa domanda e non mi piaceva continuare ad aggiungere stringhe per creare un URL. Quindi, ho iniziato a usare $ .param come spiegato da techhouse .
Ho anche trovato una libreria URI.js che crea facilmente gli URL per te. Ci sono diversi esempi che vi aiuteranno a: URI.js documentazione .
Eccone uno:

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>

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.