I have two APIs which requires two different query string/param structure, I have been trying to figure it out myself how to do this but I'm not getting anywhere.
Both APIs are GET request however API 1 URL request is something like
www.website.com/api/User?username=niceguy
API 2 request URL, because this doesn't have an input its basically just a click of a button to do its search, whereas the API 1 does have an input to build its query string structure.
www.website.com/api/User
Two different query strings but returns the same objects, I'm only using 1 search function for dynamic purpose therefore I'm finding it hard to construct my query string.
I created a function to build the query string however it only takes the API 1 structure.
Can someone point out how the HTTP request can also take API 2 structure?
function queryStringBuild() {
let result: string = "?";
//for each of the input search terms...
this.searchBoxCount.forEach((inputSearch: any) => {
// first reparse the input values to individual key value pairs
// Checks which field is not null and with empty string (space)
if (inputSearch.value != null && (inputSearch.value != "")) {
let inputValues: string = inputSearch.value
.split("\n")
.filter(function (str) { return str !== "" })
.join("&" + inputSearch.name + "=");
// then add it to the overall query string for all searches
result = result + inputSearch.name + "=" + inputValues + "&"
}
});
// remove trailing '&'
result = result.slice(0, result.length - 1);
return result;
}
API request
getRequest() {
this.http.get('www.website.com/api/' + this.queryStringBuild)
...
}
I'd propose a different solution by using URLSearchParams.
let params = new URLSearchParams();
this.searchBoxCount.forEach((inputSearch: any) => {
if (inputSearch.value != null && (inputSearch.value != "")) {
let filteredValue = inputSearch.split("\n")
.filter(x => x != "")
.join(",");
params.set(inputSearch.name, filteredValue);
}
}
this.http.get('www.website.com/api', { search: params });
I don't know exactly how your API works, so how multiple values for the same parameter get concatenated is up to you.
See this post for more information
Related
I want to adding and set parameters for query string with same key and different value .
url.com/product.php?order=price.low&order=quantity.low
so there is a same key called order with different value.
i created some radio button for change product sort.
and add event listener like this :
function lowQRadio() {
document.getElementById("radio-qlow").checked=true;
params.set("order","quantity.low");
window.location.href=(location.pathname + '?' + params);
}
function highQRadio() {
document.getElementById("radio-qhigh").checked=true;
params.set("order","quantity.high");
window.location.href=(location.pathname + '?' + params);
}
function lowPRadio(){
document.getElementById("radio-plow").checked=true;
params.set("order","price.low");
window.location.href=(location.pathname + '?' + params);
}
function highPRadio(){
document.getElementById("radio-phigh").checked=true;
params.set("order","price.high");
window.location.href=(location.pathname + '?' + params);
}
some variable defined above this code and here is variables:
let url = new URL(window.location.href);
let params = new URLSearchParams(url.search);
if(params.has("order")){
var aflag=params.getAll("order");
console.log(aflag.length);
if(aflag[aflag.length-1]==="quantity.low" || aflag[aflag.length-2]==="quantity.low") {
document.getElementById("radio-qlow").checked = true;
}
else if(aflag[aflag.length-1]==="quantity.high" || aflag[aflag.length-2]==="quantity.high"){
document.getElementById("radio-qhigh").checked=true;
}
else if(aflag[aflag.length-1]==="price.low" || aflag[aflag.length-2]==="price.low"){
document.getElementById("radio-plow").checked=true;
}
else if(aflag[aflag.length-1]==="price.high" || aflag[aflag.length-2]==="price.high"){
document.getElementById("radio-phigh").checked=true;
}
so i want when user choose sort by price and quantity ,both of this radio button will checked and query changed and if user choose one of sort method ,only one parameter set and if choose another one ,both of these checked and page will be refresh
the php code or back-end worked but js code work only for one type of radio button and both sort not working!!
please help me to fix this,thanks with regards
The query string is a name-value pair collection. Names must be unique. Do you want to do something like
url.html?OrderBy=col1,col2,col3
Use a delimited string as the query string parameter value, then in your php code split the value and use logic to apply the order by.
Recently i integrated CSGO stats in my discord bot, but today i saw that for almost every player the API sends a different json data.
Here 2 examples:
https://jsonblob.com/58688d30-26d0-11e8-b426-7b3214778399
https://jsonblob.com/52ed0c3f-26d0-11e8-b426-43058df4a5a6
My question was how to request the data properly so a win is really a win and not a kill.
.addField('**Wins:**', `${object.playerstats.stats[5].value}`, true)
.addField('**Time played:**', `${object.playerstats.stats[2].value}` + ' minutes', true)
.addField('**Kills:**', `${object.playerstats.stats[0].value}`, true)
.addField('**Deaths:**', `${object.playerstats.stats[1].value}`, true)
.addField('**Bombs planted:**',`${object.playerstats.stats[3].value}`, true)
.addField('**Money earned:**',`${object.playerstats.stats[7].value}`, true)
.addField('**Knife kills:**',`${object.playerstats.stats[9].value}`, true)
.addField('**Headshot kills:**',`${object.playerstats.stats[24].value}`, true)
.addField('**Dominations:**',`${object.playerstats.stats[39].value}`, true)
.addField('**Rounds played:**',`${object.playerstats.stats[44].value}`, true)
The name property of stats items appear to be unique enough to find. You can use array.find to look for the correct stat by name.
const stats = object.playerstats.stats
const totalKills = stats.find(s => s.name === 'total_kills').value
const totalDeaths = stats.find(s => s.name === 'total_deaths').value
Taking it further, you can use array.reduce to generate an object whose key is name and value is value for each item in the array. This way, you access it like an object.
const stats = object.playerstats.stats
const statsObj = stats.reduce((c, e) => (c[e.name] = e.value, c), {})
const totalKills = statsObj.total_kills
const totalDeaths = statsObj.total_deaths
Rather than trying to reference the array indexes, why not convert the API response into an easier-to-parse format?
// do this once...
let playerStats = {};
object.playerstats.stats.forEach(s => playerStats[s.name] = s.value);
// ...then you can use the playerStats variable however you need:
.addField('**Kills:**', `${playerStats.total_kills}`, true)
.addField('**Wins:**', `${playerStats.total_wins}`, true)
The stats array is just not sorted. you can use .find() to get the correct entry from the stats.
for example
const totalWins = object.playerstats.stats.find(stat => {
return stat.name === 'total_wins';
});
.addField('**Wins:**', `${totalWins.value}`, true)
You are approching this problem the wrong way.
JSON is not a format that is ordered. What that means is that there is no guarantee that the JSON data will return in the same order everytime. It is not a default of the API.
There is one way you could still use your way: by sorting the 'stats' array by name. but it is a long operation and not a very good idea.
The way do to this is to do a lookup by name.
For example, if you want to find the wins, you do this :
object.playerstats.stats.find(elem => elem.name === 'total_wins').value;
The find function does a lookup and returns the first element matching the predicate (elem.name === 'total_wins'). It returns null if not element matched the predicate (so be careful here).
You could do a function that returns a value for you :
findValue(statsArray, name) {
const entry = statsArray.find(elem => elem.name === name);
return entry ? entry.value : '?';
}
And then your code would look like this :
...
.addField('**Wins:**', findValue(object.playerstats.stats, 'total_wins'), true)
...
The main thing here is : never assume fields in a JSON will return the same every time. Always use lookup, and not indexes (unless it is sorted).
How to get the Object from a string?
I written a localStorage util, in it there are get and set methods.
in the set method:
function fnGet(name){
var getVal=storage.getItem(name);
if(getVal==null){
return console.log('the localstorage did\'t have'+name);
}
if((getVal.split(':-:')).lenght>1){
return eval('('+getVal.split(':-:')[0]+')');
}
return getVal.split(':-:')[0];
}
You can ignore the :-:, it is the separator of the saved data and timestamp.
there is a problem, if the data is stored a JavaScript Object, such like this:
'{"pk":1,"username":"test01","email":"","first_name":"","last_name":""}:-:1521381469910'
when I use the get method, it will become like this:
'{"pk":1,"username":"test01","email":"","first_name":"","last_name":""}'
How can I get to the JavaScript Object?
How to optimize my get method?
JSON.parse on your response from the store. localStorage stores everything as strings so you would need to stringify the object at first, as Im supposed you do as otherwise you wouldnt have been able to save it to the store.
Then to retrieve it you would need to parse it to get the javascript object again.
Two things:
Use JSON.parse() instead of eval; it's not only safer, but more descriptive as to what your intent is. Note: this requires using JSON.stringify() on the data being saved in localStorage
Correct your spelling errors; you would never get to the eval/parser block because your length was spelled "lenght"
function fnGet(name) {
let getVal = storage.getItem(name)
if (getVal == null) {
return console.log(`the localstorage did't have: ${name}`);
}
let val = getVal.split(':-:'); // for performance cache the split
if (val.length > 1) { // Spelling error: "lenght" -> length
return JSON.parse(val[0]);
}
return val[0];
}
LocalStorage saves the data stringified. So you should use JSON.parse(yourVariable) to get the data back as JSON
function fnGet(name) {
var getVal = storage.getItem(name);
if (getVal == null) {
return console.log('the localstorage did\'t have' + name);
}
if ((getVal.split(':-:')).lenght > 1) {
return eval('(' + JSON.parse(getVal.split(':-:')[0]) + ')');
}
return getVal.split(':-:')[0];
}
all you needed was JSON.parse which takes a string as an argument and if its a valid object string ,returns an object else throws an error
I am using Dexie.JS to work with IndexedDB.
Currently, have a stupid query written as:
return db.events.each((element) => {
let d = element.cause.data;
if (d.hasOwnProperty('deleted') && (false == d.deleted) &&
d.hasOwnProperty('abbreviation') &&
d.hasOwnProperty('contents') && (d.abbreviation == key)) {
snippet = d.contents;
}
}).then(() => {
return snippet;
});
It is working correctly, but slow as molasses on a large database. Should I run each on a collection made from db.events with applied where? Would that improve performance?
Thank you
Yes if assuming your "key" variable is of an indexable type: string, number, Date, TypedArray or Array, you can optimize the query like this:
First, make sure to add the index "cause.data.abbreviation" on db.events:
db.version(2).stores({
events: 'yourPrimaryKey, cause.data.abbreviation'
});
Then, rewrite the query like this:
return db.events
// Let indexedDB sort out all items matching given key:
.where('cause.data.abbreviation').equals(key)
// Filter the rest manually using Collection.filter():
.filter(element => {
let d = element.cause.data;
return (d.hasOwnProperty('deleted') && (false == d.deleted) &&
d.hasOwnProperty('contents'));
})
// Execute the query and only return the first match:
.first();
At the moment I have to check every potentially existing parameter separately.
if (req.query.param1 != undefined ) {
}
if (req.query.param2 != undefined ) {
}
if (req.query.param3 != undefined ) {
}
...
To get all query parameter:
Object.keys(req.query)
To get number of all params:
Object.keys(req.query).length
Then you can iterate through all parameters:
for(p in req.query) {
//... do something
}
UPD:
surround your request with quotes to make right query
curl -X GET "localhost:9090/mypath?param1=123¶m2=321"
without quotes the & in terminal makes the command run in the background.
If you hit /mypath?param1=5¶m2=10, then the request.query will yield {param1: 5, param2:10}.
This means that the request.query is a JavaScript object with the key as the name of the param, and value as the value of the param. Now you can do anything with it as you want: Find the length or iterate over it as follows:
for (var key in request.query) {
if (request.query.hasOwnProperty(key)) {
alert(key + " -> " + request.query[key]);
}
}
Finding only the length might not work for you that well because you may have param1 and param3, with param2 missing. Iterating will be better IMO.
You want the number of non-undefined params right?
It is as simple as this;
var no = 0;
for (var key in req.query) {
if(req.query[key]) no++;
}