Is there a way to convert this object:
{
lang: 'en-us',
episode: 12
}
To a string with the following format?
"lang=en-us&episode=12"
Much like mapping an object to a query string, where each property is a query parameter.
I can do it like this:
var parameters = [];
for(var prop in obj)
parameters.push(prop + '=' + obj[prop]);
return parameters.join('&');
But I was looking for a one-line solution. Is this possible?
PS: I cannot use jQuery and any of it utility functions. The solution must be in pure JavaScript.
You can use Array.prototype.map on the Object.keys array:
var data = {"lang": "en-us", "episode": 12};
var str = Object.keys(data).map(function (key) {
return "" + key + "=" + data[key]; // line break for wrapping only
}).join("&");
console.log(str);
With ES6, this becomes even more terse:
var data = {"lang": "en-us", "episode": 12};
var str = Object.keys(data).map(key => `${key}=${data[key]}`).join("&");
console.log(str);
You could use
var myObj ={"lang": "en-us", "episode": 12};
var str = Object.keys(myObj).map(key => key+"="+myObj[key]).join("&");
Whether or not this is any more readable is another question :)
All the other answers work perfectly,
However I've found that you can use URLSearchParams for the same thing...
var myObj = {keyOne: 'keyOneValue', keyTwo: 'keyTwoValue'};
var queryParams = new URLSearchParams(myObj).toString();
console.log(queryParams);
// keyOne=keyOneValue&keyTwo=keyTwoValue
see: https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams
Object.entries (ES6)
Object.entries returns [key, value] pairs, so we can destructure and map the pairs directly into ${key}=${value}:
Object.entries(params).map(([key, value]) => `${key}=${value}`).join('&');
// "lang=en-us&episode=12"
URLSearchParams
For the specific use case of query strings, use URLSearchParams.toString:
let searchParams = new URLSearchParams(params);
searchParams.toString();
// "lang=en-us&episode=12"
URLSearchParams provides an interface with common utility methods, e.g.:
searchParams.get('episode');
// "12"
searchParams.sort();
// "episode=12&lang=en-us"
searchParams.set('episode', 123456);
// "episode=123456&lang=en-us"
If the value contains equalTo (=) symbol, the accepted solution will not work.
Example
key1=a,key2=b,keyc=keyof=thec
accesskey=absdsfdfsa===
Solution:
Better to use Regex,
const a =
'AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;DefaultEndpointsProtocol=http;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;QueueEndpoint=http://127.0.0.1:10001/devstoreaccount1;TableEndpoint=http://127.0.0.1:10002/devstoreaccount1';
const output = {};
a.split(';').forEach((v, i) => {
const [key, value] = v.split(RegExp(/=(.*)/));
output[key] = value;
})
console.log(output);
output
Note: AccountKey contains == in value
{
AccountName: 'devstoreaccount1',
AccountKey: 'Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==',
DefaultEndpointsProtocol: 'http',
BlobEndpoint: 'http://127.0.0.1:10000/devstoreaccount1',
QueueEndpoint: 'http://127.0.0.1:10001/devstoreaccount1',
TableEndpoint: 'http://127.0.0.1:10002/devstoreaccount1'
}
Related
I have this String result:tie,player:paper,computer:paper
I guess you could split into arrays and make a object and parse it an object, however this does not seem to be a good approach.
How would I get this String as a object?
let string = "result:tie,player:paper,computer:paper"
For this particular string, I'd turn the string into proper JSON by surrounding the keys and values with "s, and then use JSON.parse:
const string = "result:tie,player:paper,computer:paper";
const json = '{' + string.replace(/(\w+):(\w+)/g, `"$1":"$2"`) + '}';
console.log(JSON.parse(json));
Though, ideally, whatever serves you that string should be giving you something in JSON format, rather than forcing you to resort to a hacky method like this to deal with a broken input.
Split on ,, iterate through, and split each string on : and make an object key/value property based on that. Use destructuring for simplicity:
let string = "result:tie,player:paper,computer:paper";
let obj = {};
let propsArr = string.split(",");
propsArr.forEach(s => {
var [key, value] = s.split(":");
obj[key] = value;
});
console.log(obj);
Split on the , to get key:value tokens, split those by : to get the key and value, and add them to the reduced object that collects the key value pairs.
var temp = "result:tie,player:paper,computer:paper";
var obj = temp.split(',').reduce((result, token)=>{
var [key, value] = token.split(':');
result[key] = value;
return result;
}, {});
console.log(obj);
I want to fetch a particular value from a javascript string without using methods like indexOf or substr. Is there any predefined method of doing so?
For e.g., I have a string,
var str = "a=1|b=2|c=3|d=4|e=5|f=6";
I want to fetch the value of c from above string, how can I achieve it directly?
You can try with:
str.split('|').find(value => value.startsWith('c=')).split('=')[1]
You can also convert it into an object with:
const data = str.split('|').reduce((acc, val) => {
const [key, value] = val.split('=');
acc[key] = value;
return acc;
}, {});
data.c // 3
In this case, use split:
var str = "a=1|b=2|c=3|d=4|e=5|f=6";
var parts = str.split('|');
var value = parts[2].split('=')[1];
console.log(value);
Or maybe map it, to get all values to work with afterwards:
var str = "a=1|b=2|c=3|d=4|e=5|f=6";
var values = str.split('|').map(e => e.split('='));
console.log(values);
Using regex can solve this problem
const str = "a=1|b=2|c=3|d=4|e=5|f=6";
const matches = str.match(/c=([0-9]+)/);
console.log(matches[1]);
Ref:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/match
Try this -
var str = "a=1|b=2|c=3|d=4|e=5|f=6";
str.split('|')[2].split('=')[1];
You could turn that string into an associative array or an object
var str = "a=1|b=2|c=3|d=4|e=5|f=6";
var obj = {}; //[] for array
str.split("|").map(o => {
var el = o.split("=");
obj[el[0]] = el[1];
})
console.log(obj.a)
console.log(obj.b)
console.log(obj.c)
I suggest first splitting and mapping into some form of readable data structure. Finding by string is vulnerable to typos.
const mappedElements = str
.split('|')
.map(element => element.split('='))
.map(([key, value]) => ({ key: value }));
Array filter method can be memory efficient for such operation.
var cOutput = str.split('|').filter( (val) => {
const [k,v] = val.split('=');
return k=='c' ? v : false }
)[0].split('=')[1];
See Array Filter
I have a localstorage object, and I need to find all data and extract it based on the key.
Example of object:
Storage {
agency-list|radio-radio2: "true",
agency|radio-radio1: "true", length: 2
.....}
This is how I get the param for searching:
let formID = $('form').attr('id');
let regex = new RegExp("^" + formID + "|");
For example, I would like to extract all key value, where the key is beginning with agency|, in separate array or object.
What is the best approach for this problem?
You can use Object.keys() method to iterate over your keys
let Storage = {
"agency-list|radio-radio2": "true",
"agency|radio-radio1": "true",
length: 2 }
let otherStorage = [];
Object.keys(Storage).forEach(key=>{
if(key.startsWith("agency|")){
otherStorage.push(key);
}
});
console.log(otherStorage);
A combination Object.keys() and filter can help you :
let formID = $('form').attr('id');
let regex = new RegExp(`^${formID}|`);
const Storage = {
"agency-list|radio-radio2": "true",
"agency|radio-radio1": "true",
length: 2
};
const agencies = Object.keys(Storage).filter( key => regex.test(key));
Simply loop through all your object's properties, test if the prop matches the regex, and add it to result if it does.
let result = {};
for(let prop in storage){
if(prop.match(regex)){
result[prop] = storage[prop];
}
}
Turn your storage into an array with Object.entries
Filter the entries with Array#filter and check the regex with test.
Put everything back together into an object with Array#reduce
I also used destructuring parameters [key, value], since Object.entries outputs everything as an array of [key, value] arrays.
let formID = $('form').attr('id');
let regex = new RegExp("^" + formID + "|");
Object.entries(localStorage)
.filter(([key, value]) => regex.test(key))
.reduce((obj, [key, value]) => (obj[key] = value, obj), {});
This question already has answers here:
How can I get query string values in JavaScript?
(73 answers)
Closed 4 years ago.
If I had a URL such as
http://localhost/search.php?year=2008
How would I write a JavaScript function to grab the variable year and see if it contains anything?
I know it can be done with location.search but I can’t figure out how it grabs parameters.
You may use window.URL class:
new URL(location.href).searchParams.get('year')
// Returns 2008 for href = "http://localhost/search.php?year=2008".
// Or in two steps:
const params = new URL(location.href).searchParams;
const year = params.get('year');
My favorite way for getting URL params is this approach:
var parseQueryString = function() {
var str = window.location.search;
var objURL = {};
str.replace(
new RegExp( "([^?=&]+)(=([^&]*))?", "g" ),
function( $0, $1, $2, $3 ){
objURL[ $1 ] = $3;
}
);
return objURL;
};
//Example how to use it:
var params = parseQueryString();
alert(params["foo"]);
A non-regex approach, you can simply split by the character '&' and iterate through the key/value pair:
function getParameter(paramName) {
var searchString = window.location.search.substring(1),
i, val, params = searchString.split("&");
for (i=0;i<params.length;i++) {
val = params[i].split("=");
if (val[0] == paramName) {
return val[1];
}
}
return null;
}
2020 EDIT:
Nowadays, in modern browsers you can use the URLSearchParams constructor:
const params = new URLSearchParams('?year=2020&month=02&day=01')
// You can access specific parameters:
console.log(params.get('year'))
console.log(params.get('month'))
// And you can iterate over all parameters
for (const [key, value] of params) {
console.log(`Key: ${key}, Value: ${value}`);
}
This question is old and things have evolved in JavaScript.
You can now do this:
const params = {}
document.location.search.substr(1).split('&').forEach(pair => {
[key, value] = pair.split('=')
params[key] = value
})
and you get params.year that contains 2008.
You would also get other query params in your params object.
Edit: a shorter/cleaner way to do this:
const params = new Map(location.search.slice(1).split('&').map(kv => kv.split('=')))
You can then test if the year param exists with:
params.has('year') // true
Or retrieve it with:
params.get('year') // 2008
Edit 2020
You can convert URL params to an Object:
const params = location.search.slice(1).split('&').reduce((acc, s) => {
const [k, v] = s.split('=')
return Object.assign(acc, {[k]: v})
}, {})
Then it can be used as a regular JS Object:
params.year // 2008
The following uses regular expressions and searches only on the query string portion of the URL.
Most importantly, this method supports normal and array parameters as in
http://localhost/?fiz=zip&foo[]=!!=&bar=7890#hashhashhash
function getQueryParam(param) {
var result = window.location.search.match(
new RegExp("(\\?|&)" + param + "(\\[\\])?=([^&]*)")
);
return result ? result[3] : false;
}
console.log(getQueryParam("fiz"));
console.log(getQueryParam("foo"));
console.log(getQueryParam("bar"));
console.log(getQueryParam("zxcv"));
Output:
zip
!!=
7890
false
It took me a while to find the answer to this question. Most people seem to be suggesting regex solutions. I strongly prefer to use code that is tried and tested as opposed to regex that I or someone else thought up on the fly.
I use the parseUri library available here:
http://stevenlevithan.com/demo/parseuri/js/
It allows you to do exactly what you are asking for:
var uri = 'http://localhost/search.php?year=2008';
var year = uri.queryKey['year'];
// year = '2008'
function gup( name ) {
name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
var regexS = "[\\?&]"+name+"=([^&#]*)";
var regex = new RegExp( regexS );
var results = regex.exec( window.location.href );
if( results == null )
return "";
else
return results[1];
}
var year = gup("year"); // returns "2008"
The easiest way is to have
if (document.location.search.indexOf('yourtext=') >= 0) {
// your code
} else {
// what happens?
}
indexOf()
The indexOf(text) function returns
A WHOLE NUMBER BELOW 0 when the text passed in the function is not in whatever variable or string you are looking for - in this case document.location.search.
A WHOLE NUMBER EQUAL TO 0 OR HIGHER when the text passed in the function is in whatever variable or string you are looking for - in this case document.location.search.
I hope this was useful, #gumbo
A Simple One-Line Solution:
let query = Object.assign.apply(null, location.search.slice(1).split('&').map(entry => ({ [entry.split('=')[0]]: entry.split('=')[1] })));
Expanded & Explained:
// define variable
let query;
// fetch source query
query = location.search;
// skip past the '?' delimiter
query = query.slice(1);
// split source query by entry delimiter
query = query.split('&');
// replace each query entry with an object containing the query entry
query = query.map((entry) => {
// get query entry key
let key = entry.split('=')[0];
// get query entry value
let value = entry.split('=')[1];
// define query object
let container = {};
// add query entry to object
container[key] = value;
// return query object
return container;
});
// merge all query objects
query = Object.assign.apply(null, query);
I used a variant of Alex's - but needed to to convert the param appearing multiple times to an array. There seem to be many options. I didn't want rely on another library for something this simple. I suppose one of the other options posted here may be better - I adapted Alex's because of the straight forwardness.
parseQueryString = function() {
var str = window.location.search;
var objURL = {};
// local isArray - defer to underscore, as we are already using the lib
var isArray = _.isArray
str.replace(
new RegExp( "([^?=&]+)(=([^&]*))?", "g" ),
function( $0, $1, $2, $3 ){
if(objURL[ $1 ] && !isArray(objURL[ $1 ])){
// if there parameter occurs more than once, convert to an array on 2nd
var first = objURL[ $1 ]
objURL[ $1 ] = [first, $3]
} else if(objURL[ $1 ] && isArray(objURL[ $1 ])){
// if there parameter occurs more than once, add to array after 2nd
objURL[ $1 ].push($3)
}
else
{
// this is the first instance
objURL[ $1 ] = $3;
}
}
);
return objURL;
};
I played a bit with this problem and at this end I used this:
function getJsonFromUrl() {
return Object.assign(...location.search.substr(1).split("&").map(sliceProperty));
}
Object.assign to transform a list of object into one object
Spread operator ... to transform an array into a list
location.search.substr(1).split("&") to get all parameters as array of properties (foo=bar)
map walk each properties and split them into an array (either call splitProperty or sliceProperty).
splitProperty:
function splitProperty(pair) {
[key, value] = pair.split("=")
return { [key]: decodeURIComponent(value) }
}
Split by =
Deconstruct the array into an array of two elements
Return a new object with the dynamic property syntax
sliceProperty:
function sliceProperty(pair) {
const position = pair.indexOf("="),
key = pair.slice(0, position),
value = pair.slice(position + 1, pair.length);
return { [key]: decodeURIComponent(value) }
}
Set the position of =, key and value
Return a new object with the dynamic property syntax
I think splitProperty is prettier but sliceProperty is faster. Run JsPerf for more information.
Grab the params from location.search with one line:
const params = new Map(this.props.location.search.slice(1).split('&').map(param => param.split('=')))
Then, simply:
if(params.get("year")){
//year exists. do something...
} else {
//year doesn't exist. do something else...
}
ES6 answer:
const parseQueryString = (path = window.location.search) =>
path.slice(1).split('&').reduce((car, cur) => {
const [key, value] = cur.split('=')
return { ...car, [key]: value }
}, {})
for example:
parseQueryString('?foo=bar&foobar=baz')
// => {foo: "bar", foobar: "baz"}
This is what I like to do:
window.location.search
.substr(1)
.split('&')
.reduce(
function(accumulator, currentValue) {
var pair = currentValue
.split('=')
.map(function(value) {
return decodeURIComponent(value);
});
accumulator[pair[0]] = pair[1];
return accumulator;
},
{}
);
Of course you can make it more compact using modern syntax or writing everything into one line...
I leave that up to you.
Is there any way to create the query parameters for doing a GET request in JavaScript?
Just like in Python you have urllib.urlencode(), which takes in a dictionary (or list of two tuples) and creates a string like 'var1=value1&var2=value2'.
Here you go:
function encodeQueryData(data) {
const ret = [];
for (let d in data)
ret.push(encodeURIComponent(d) + '=' + encodeURIComponent(data[d]));
return ret.join('&');
}
Usage:
const data = { 'first name': 'George', 'last name': 'Jetson', 'age': 110 };
const querystring = encodeQueryData(data);
URLSearchParams has increasing browser support.
const data = {
var1: 'value1',
var2: 'value2'
};
const searchParams = new URLSearchParams(data);
// searchParams.toString() === 'var1=value1&var2=value2'
Node.js offers the querystring module.
const querystring = require('querystring');
const data = {
var1: 'value1',
var2: 'value2'
};
const searchParams = querystring.stringify(data);
// searchParams === 'var1=value1&var2=value2'
functional
function encodeData(data) {
return Object.keys(data).map(function(key) {
return [key, data[key]].map(encodeURIComponent).join("=");
}).join("&");
}
Zabba has provided in a comment on the currently accepted answer a suggestion that to me is the best solution: use jQuery.param().
If I use jQuery.param() on the data in the original question, then the code is simply:
const params = jQuery.param({
var1: 'value',
var2: 'value'
});
The variable params will be
"var1=value&var2=value"
For more complicated examples, inputs and outputs, see the jQuery.param() documentation.
ES2017 (ES8)
Making use of Object.entries(), which returns an array of object's [key, value] pairs. For example, for {a: 1, b: 2} it would return [['a', 1], ['b', 2]]. It is not supported (and won't be) only by IE.
Code:
const buildURLQuery = obj =>
Object.entries(obj)
.map(pair => pair.map(encodeURIComponent).join('='))
.join('&');
Example:
buildURLQuery({name: 'John', gender: 'male'});
Result:
"name=John&gender=male"
We've just released arg.js, a project aimed at solving this problem once and for all. It's traditionally been so difficult but now you can do:
var querystring = Arg.url({name: "Mat", state: "CO"});
And reading works:
var name = Arg("name");
or getting the whole lot:
var params = Arg.all();
and if you care about the difference between ?query=true and #hash=true then you can use the Arg.query() and Arg.hash() methods.
This should do the job:
const createQueryParams = params =>
Object.keys(params)
.map(k => `${k}=${encodeURI(params[k])}`)
.join('&');
Example:
const params = { name : 'John', postcode: 'W1 2DL'}
const queryParams = createQueryParams(params)
Result:
name=John&postcode=W1%202DL
If you are using Prototype there is Form.serialize
If you are using jQuery there is Ajax/serialize
I do not know of any independent functions to accomplish this, though, but a google search for it turned up some promising options if you aren't currently using a library. If you're not, though, you really should because they are heaven.
The built-in URL class provides a convenient interface for creating and parsing URLs.
There are no networking methods that require exactly a URL object, strings are good enough. So technically we don’t have to use URL. But sometimes it can be really helpful.
👇 Example
let url = new URL("https://google.com/search");
url.searchParams.set('var1', "value1");
url.searchParams.set('var2', "value2");
url.searchParams.set('var3', "value3");
url.searchParams.set('var4', "value4 has spaces");
console.log(url)
A little modification to typescript:
public encodeData(data: any): string {
return Object.keys(data).map((key) => {
return [key, data[key]].map(encodeURIComponent).join("=");
}).join("&");
}
Just like to revisit this almost 10 year old question. In this era of off-the-shelf programming, your best bet is to set your project up using a dependency manager (npm). There is an entire cottage industry of libraries out there that encode query strings and take care of all the edge cases. This is one of the more popular ones -
https://www.npmjs.com/package/query-string
Here is an example:
let my_url = new URL("https://stackoverflow.com")
my_url.pathname = "/questions"
const parameters = {
title: "just",
body: 'test'
}
Object.entries(parameters).forEach(([name, value]) => my_url.searchParams.set(name, value))
console.log(my_url.href)
I have improved the function of shog9`s to handle array values
function encodeQueryData(data) {
const ret = [];
for (let d in data) {
if (typeof data[d] === 'object' || typeof data[d] === 'array') {
for (let arrD in data[d]) {
ret.push(`${encodeURIComponent(d)}[]=${encodeURIComponent(data[d][arrD])}`)
}
} else if (typeof data[d] === 'null' || typeof data[d] === 'undefined') {
ret.push(encodeURIComponent(d))
} else {
ret.push(`${encodeURIComponent(d)}=${encodeURIComponent(data[d])}`)
}
}
return ret.join('&');
}
Example
let data = {
user: 'Mark'
fruits: ['apple', 'banana']
}
encodeQueryData(data) // user=Mark&fruits[]=apple&fruits[]=banana
By using queryencoder, you can have some nice-to-have options, such custom date formatters, nested objects and decide if a val: true will be just value or value=true.
const { encode } = require('queryencoder');
const object = {
date: new Date('1999-04-23')
};
// The result is 'date=1999-04-23'
const queryUrl = encode(object, {
dateParser: date => date.toISOString().slice(0, 10)
});
const base = "https://www.facebook.com"
const path = '/v15.0/dialog/oauth'
const params = new URLSearchParams({
client_id: clientID,
redirect_uri: redirectUri,
state: randomState,
})
const url = new URL(`${path}?${params.toString()}`, base)
Here's an example to create query parameters and build URL from base using only JavaScript built-in constructor.
This is part of Facebook Login implementation in manual approach.
According to URLSearchParams doc's example, there's a line
const new_url = new URL(`${url.origin}${url.pathname}?${new_params}`);
and I've followed that practice.
This is by far the most standardized way to build URL I believe.
I was a bit surprised that JavaScript doesn't supports query or fragment arguments in thier URL constructor still in 2023, despite It's definately worth having that.
This thread points to some code for escaping URLs in php. There's escape() and unescape() which will do most of the work, but the you need add a couple extra things.
function urlencode(str) {
str = escape(str);
str = str.replace('+', '%2B');
str = str.replace('%20', '+');
str = str.replace('*', '%2A');
str = str.replace('/', '%2F');
str = str.replace('#', '%40');
return str;
}
function urldecode(str) {
str = str.replace('+', ' ');
str = unescape(str);
return str;
}