Nested loop not getting expected result - javascript

Am having the arrays,
Now i need to get all tab names looping through and exclude the values present in exclude.
json1 ={
"sku Brand": "abc",
"strngth": "ALL",
"area": "",
"Country": "",
"local Brand": "",
"theme": "HideDisNameFilters"
}
json2 = {
"nav": [{
"tabname": "tab1",
"exclude':["area',"xyz"]
},
{
"tabname": "tab2",
"exclude":["Country"]
}
]}
var obj1 = json2.nav;
console.log(obj1)
Object.keys(obj1).forEach(function(prop) {
var str1 = "";
var maxLength = Object.keys(json1).length-2
Object.keys(json1).forEach(key => {
var str = "";
var t1 = "";
var index = Object.keys(json1).indexOf(key);
if(key != "theme"){
if(!obj1[prop]['exclude'].includes(key)){
str = key + "="+ json1[key];
str1 +=str&
console.log("str",str, " = ",str1 )
if(maxLength == index){
var t1 = "<a href="+str1 + "target='_blank'>"+ obj1[prop]['tabname'] +"</a>"
final_array.push(t1)
}
}
}
});
});
o/p should be: (it will exclude and form the url by checking from exclude array as below)
["<a href='sku+Brand=abc&Strngth=ALL&Country=&local+Brand=&' "target='_blank'>tab1<a>,"<a href='sku+Brand=abc&Strngth=ALL&area=&local+Brand=&' "target='_blank'>tab2<a>"]
AM not getting the correct output as expected...

Your code has several syntax errors (unbalanced quotes, mismatching quotes, trailing & without quotes, ...), and variables that have not been defined with var, let or const. It assigns to key_for_url, but never uses that value. It references a "slug" property, but that doesn't exist in your input data. It assumes a certain key order in plain objects, as it uses indexOf on Object.keys. This is a code smell. Variable names json1 and json2 are not very descriptive.
Here is code you could use:
let filter = {
"sku Brand": "abc",
"strngth": "ALL",
"area": "",
"Country": "",
"local Brand": "",
"theme": "HideDisNameFilters"
}
let tabs = {
"nav": [{
"tabname": "tab1",
"exclude": ["area", "xyz"]
},
{
"tabname": "tab2",
"exclude": ["Country"]
}
]
}
let result = tabs.nav.map(({tabname, exclude}) =>
`<a href='${
Object.entries(filter)
.filter(([key]) => !exclude.includes(key) && key != "theme")
.map(([key, value]) => `${key}=${value}`)
.join("&")
}' target='_blank'>${tabname}</a>`
);
console.log(result);

Solution:
obj1 is an array, so the loop will be obj1.forEach and accessing the value will be prop['exclude'].
I have made the code a bit more short.
json1 = {
"sku Brand": "abc",
"strngth": "ALL",
"area": "",
"Country": "",
"local Brand": "",
"theme": "HideDisNameFilters"
}
json2 = {
"nav": [{
"tabname": "tab1",
"exclude": ["area", "xyz"]
},
{
"tabname": "tab2",
"exclude": ["Country"]
}
]
}
final_array = []
var obj1 = json2.nav;
obj1.forEach(function (prop) {
let str = "";
Object.keys(json1).forEach((key) => {
if (!prop['exclude'].includes(key) && key !== 'theme') {
newKey = key.split(' ').join('+');
str = str + newKey + '=' + json1[key] + "&";
}
})
var t1 = "<a href=" + "'" + str + "'" + " target = '_blank' > "+ prop['tabname'] +" < /a>"
final_array.push(t1)
});
console.log(final_array)

Related

Can not iterate through Javascript Object

I have the following object (return from Insomnia)
[
{
"field": 10.5,
"this_is_a_bool": 1,
"name": "",
"data": "2018-05-22T03:00:00.000Z",
"field2": null
},
{
"field": 5.3,
"this_is_a_bool": 0,
"name": "Slim Shady",
"data": "2020-01-22T04:45:00.000Z",
"field2": null
}
]
The problem is that I can't iterate over those "set of values" so I can edit them.
To do something like this:
for (const val in myObj) {
if (val.field2 === null) {
val.field1 = 'flag - ' + val.field1
}
}
What I've tried:
for (const val in myObj)
for (const val of myObj)
const [key,value] of Object.entries(myObj)
Errors: Sometimes it says myObj is not iterable and sometimes the code is just ignored.
Why don't you use simple .map():
const src = [{"field":10.5,"this_is_a_bool":1,"name":"","data":"2018-05-22T03:00:00.000Z","field2":null},{"field":5.3,"this_is_a_bool":0,"name":"Slim Shady","data":"2020-01-22T04:45:00.000Z","field2":null}],
result = src.map(({field, field2, ...rest}) => ({
field: field2 === null ? `flag-${field}` : field,
field2,
...rest
}))
console.log(result)
.as-console-wrapper{min-height:100%;}
or... if you still want using for loop...
(in your sample val is key)
var myObj = [
{
"field": 10.5,
"this_is_a_bool": 1,
"name": "",
"data": "2018-05-22T03:00:00.000Z",
"field2": null
},
{
"field": 5.3,
"this_is_a_bool": 0,
"name": "Slim Shady",
"data": "2020-01-22T04:45:00.000Z",
"field2": null
}
];
for (const val in myObj) {
if (myObj[val].field2 === null){
myObj[val].field = 'flag - ' + myObj[val].field;
}
}
console.log(myObj);

How to stringify an Object which includes objects of array?

How to manipulate this object to URL query parameter.The example the the query parameter should be
advocates=7195&categories=25&checkbox-active=true&checkbox-close=undefined&checkbox-filed=true&checkbox-notFiled=undefined&cities=Delhi&cities=mumbai
Here is the code to convert any json no matter how deep it is into query params:
var o = {
"stage": 50,
"categories": [25, 23, 28],
"advocates": [{
"key": "7195",
"label": "kallol saikia"
}],
"cities": [{
"key": 390,
"label": "Delhi"
}, {
"key": 6,
"label": "Mumbai"
}],
"checkbox-filed": true,
"checkbox-active": true
}
function getParams(key, value) {
var queries = [];
var newKey;
if (Array.isArray(value)) {
for (var i = 0; i < value.length; i++) {
newKey = key + "[" + i + "]";
queries = queries.concat(getParams(newKey, value[i]));
}
} else if (value && typeof value === 'object' && value.constructor === Object) {
for (var prop in value) {
if (value.hasOwnProperty(prop)) {
newKey = key ? key + "[" + prop + "]" : prop;
queries = queries.concat(getParams(newKey, value[prop]));
}
}
} else {
queries.push(key + "=" + value);
}
return queries;
}
var query = getParams("", o).join("&");
console.log(query);
I hope this solves your issue.
Maybe:
var o = {
'advocates': [{
key: 1
}],
'checkbox-active': true
};
var query = Object.keys(o).map(function(i) {
var val;
if (Array.isArray(o[i])) {
val = o[i][0].key;
} else {
val = o[i];
}
return i + '=' + val;
}).join('&');
console.log(query);
You can try using Post Request
Send a JSON String using JSON.Parse() and JSON.stringify()
Convert your params array to JSON String and send that as a single query param.
Decode the query string param (i.e JSON string)
Adding Example
var jsonString = JSON.stringify({
"stage": 50,
"categories": [25, 23, 28],
"advocates": [{
"key": "7195",
"label": "kallol saikia"
}],
"cities": [{
"key": 390,
"label": "Delhi"
}, {
"key": 6,
"label": "Mumbai"
}],
"checkbox-filed": true,
"checkbox-active": true
});
// Pass down the Encoded Json
var encodedJson = encodeURI(jsonString);
console.log(encodedJson);
// Decode Json
var decodedJson = decodeURI(encodedJson);
var decodedObject = JSON.parse(decodedJson);
console.log(decodedObject);
Output
"%7B%22stage%22:50,%22categories%22:%5B25,23,28%5D,%22advocates%22:%5B%7B%22key%22:%227195%22,%22label%22:%22kallol%20saikia%22%7D%5D,%22cities%22:%5B%7B%22key%22:390,%22label%22:%22Delhi%22%7D,%7B%22key%22:6,%22label%22:%22Mumbai%22%7D%5D,%22checkbox-filed%22:true,%22checkbox-active%22:true%7D"
Object { stage: 50, categories: Array [25, 23, 28], advocates: Array [Object { key: "7195", label: "kallol saikia" }], cities: Array [Object { key: 390, label: "Delhi" }, Object { key: 6, label: "Mumbai" }], checkbox-filed: true, checkbox-active: true }
This algorithm will work. Just with caution, if you change the object structure, this might break
Hope this helps :>
var obj = {
"stage": 50,
"categories": [25, 23, 28],
"advocates": [{
"key": "7195",
"label": "kallol saikia"
}],
"cities": [{
"key": 390,
"label": "Delhi"
}, {
"key": 6,
"label": "Mumbai"
}],
"checkbox-filed": true,
"checkbox-active": true
}
let str = 'advocates=' + obj.advocates[0].key +
'&categories=' + obj.categories[0] +
'checkbox-active=' + obj['checkbox-active'] +
'checkbox-close=' + obj['checkbox-close'] +
'checkbox-filed=' + obj['checkbox-filed'] +
'checkbox-notFiled=' + obj['checkbox-notFiled'];
obj.cities.forEach(city=>str+= 'cities=' + city.label + '&')
str = str.substring(0,str.length-1)
console.log(str)
advocates=7195&
categories=25&
checkbox-active=true&
checkbox-close=undefined&
checkbox-filed=true&
checkbox-notFiled=undefined&
cities=Delhi&
cities=mumbai
`${key}${i>0?'&':''}${val[0]}=${val[1]}`, ""
'advocates':
'checkbox-active':
'checkbox-close':
'checkbox-filed':
'checkbox-notFiled':
arrStr += key[0] + '=';
arrStr += key[1][0].key + '&';
Here is an example I just made: https://jsfiddle.net/BrandonQDixon/surwf7gd
The script below will loop through the keys of an object and convert them to GET style parameters, which is what your request looks like. I made it a function so you can directly call it on an object.
This will also work recursively, if your object has nested objects, but understand that if nested objects have some of the same keys (or there are duplicates in general), they will both be added to the string.
/**
* This will turn an object into a GET style parameter
* This scans recursively if 2nd param is set to true, but "flattens" every property into one string, so this may cause some overriding
* This will encode the keys and values if 3rd param is set to true
*/
function paramatize(obj,recursive = true,encode = true) {
let str = "";
let len = Object.keys(obj).length
let i = 0;
for (let key in obj) {
i++;
if (typeof obj[key] === 'object' && recursive) {
str += paramatize(obj[key]);
} else {
let nKey = (encode)?encodeURIComponent(key):key;
let nValue = (encode)?encodeURIComponent(obj[key]):obj[key];
str += nKey+"="+nValue;
}
if (i < len) {
str += "&";
}
}
return str;
}

How to parse nested JSON in Javascript?

I am trying to parse and show JSON data (product catalog) using XMLHttpRequest method. I am able to display the brands and their names, but not able to showcase list of products progmatically.
Here is the sample JSON request:
{
"products": {
"laptop": [{
"brand": "sony",
"price": "$1000"
}, {
"brand": "acer",
"price": "$400"
}],
"cellphone": [{
"brand": "iphone",
"price": "$800"
}, {
"brand": "htc",
"price": "$500"
}],
"tablets": [{
"brand": "iPad",
"price": "$800"
}, {
"brand": "htc-tab",
"price": "$500"
}]
}
}
Right now I am using following code to show data in tabluar form:
function loadJSON() {
var data_file = "http://localhost/AJAX/productcatalog.json";
var http_request = new XMLHttpRequest();
http_request.onreadystatechange = function () {
if ((http_request.readyState == 4) && (http_request.status == 200)) {
// Javascript function JSON.parse to parse JSON data
var jsonObj = JSON.parse(http_request.responseText);
data = '<table border="2"><tr><td>Type</td><td>Brand</td><td>Price</td></tr>';
var i = 0;
debugger;
for (i = 0; i < jsonObj["products"].laptop.length; i++)
{
obj = jsonObj["products"].laptop[i];
data = data + '<tr><td>laptop</td><td>' + obj.brand + '</td><td>' + obj.price + '</td></tr>';
}
for (i = 0; i < jsonObj["products"].cellphone.length; i++)
{
obj = jsonObj["products"].cellphone[i];
data = data + '<tr><td>laptop</td><td>' + obj.brand + '</td><td>' + obj.price + '</td></tr>';
}
for (i = 0; i < jsonObj["products"].tablets.length; i++)
{
obj = jsonObj["products"].tablets[i];
data = data + '<tr><td>laptop</td><td>' + obj.brand + '</td><td>' + obj.price + '</td></tr>';
}
data += '</table>';
document.getElementById("demo").innerHTML = data;
}
}
http_request.open("GET", data_file, true);
http_request.send();
}
Question What is the way to fetch product list , i.e. products, cellphone and tablets ? Right now I have hardcoded that in order to fetch complete list of brands. Please advice. (I want to use plain javascript and not jquery)
Thanks!
It sounds like what you're missing is the "How do I iterate over an object when I don't know all the keys".
An object is a set of key, value pairs. You can use for/in syntax: for( var <key> in <object> ){} to get each key.
For your use case it might be something like:
var products = jsonObject['products'];
for( var productName in products ){
//productName would be "laptop", "cellphone", etc.
//products[productName] would be an array of brand/price objects
var product = products[productName];
for( var i=0; i<product.length; i++ ){
//product[i].brand
//product[i].price
}
}
In practice, I might use something a little less verbose, but this makes it easier to understand what is going on.
To achieve the expected i have used for loop and HTML DOM createElement() Method
var product_catalog = {
"products": {
"laptop": [{
"brand": "sony",
"price": "$1000"
}, {
"brand": "acer",
"price": "$400"
}],
"cellphone": [{
"brand": "iphone",
"price": "$800"
}, {
"brand": "htc",
"price": "$500"
}],
"tablets": [{
"brand": "iPad",
"price": "$800"
}, {
"brand": "htc-tab",
"price": "$500"
}]
}
};
var output = document.querySelector('#product tbody');
function build(JSONObject) {
/**get all keys***/
var keys = Object.keys(JSONObject);
/**get all subkeys***/
var subkeys = Object.keys(JSONObject[keys]);
console.log(subkeys);
/**loop sub keys to build HTML***/
for (var i = 0, tr, td; i < subkeys.length; i++) {
tr = document.createElement('tr');
td = document.createElement('td');
td.appendChild(document.createTextNode(subkeys[i]));
tr.appendChild(td);
output.appendChild(tr);
}
};
build(product_catalog);
HTML:
Coepen URL for reference- http://codepen.io/nagasai/pen/xOOqMv
Hope this works for you :)
Look at this example:
var x = data.key1.children.key4;
var path = "data";
function search(path, obj, target) {
for (var k in obj) {
if (obj.hasOwnProperty(k))
if (obj[k] === target)
return path + "['" + k + "']"
else if (typeof obj[k] === "object") {
var result = search(path + "['" + k + "']", obj[k], target);
if (result)
return result;
}
}
return false;
}
//Then for evry node that you need you can call the search() function.
var path = search(path, data, x);
console.log(path); //data['key1']['children']['key4']
I think this is what you're asking about, you can use Object.keys to get the properties of an object, then loop through them afterward.
var data = {
"products": {
"laptop": [{
"brand": "sony",
"price": "$1000"
}, {
"brand": "acer",
"price": "$400"
}],
"cellphone": [{
"brand": "iphone",
"price": "$800"
}, {
"brand": "htc",
"price": "$500"
}],
"tablets": [{
"brand": "iPad",
"price": "$800"
}, {
"brand": "htc-tab",
"price": "$500"
}]
}
}
var typesOfProducts = Object.keys(data.products)
console.log(typesOfProducts)
document.getElementById('output').textContent = typesOfProducts.toString()
//Then, to loop through
var i = -1,
len = typesOfProducts.length
function handleProduct(productType) {
console.log("This is the " + productType + " data.")
console.log(data.products[productType])
}
while (++i < len) {
handleProduct(typesOfProducts[i])
}
<div id="output"></div>
It sounds like what you're looking for is just an array of the keys of the "products" object. Example:
Products: ["laptop", "cellphone", "tablets"];
If so, I would just run your json object through javascript's Object.keys() method.
var jsonObj = JSON.parse(http_request.responseText);
var products = Object.keys(jsonObj.products);
// products = ["laptop", "cellphone", "tablets"];

Convert CSV file to JSON dictionary?

I need to convert a large CSV data set to JSON, however the output should be a JSON dictionary like this:
var products = {
"crystal": {
"description": "This is a crystal",
"price": "2.95"
},
"emerald": {
"description": "This is a emerald",
"price": "5.95"
}
};
This is what the CSV table would look like:
I am using a script referenced here to generate the JSON:
var csv = require('csv')
var fs = require('fs')
var f = fs.createReadStream('Fielding.csv')
var w = fs.createWriteStream('out.txt')
w.write('[');
csv()
.from.stream(f, {columns:true})
.transform(function(row, index) {
return (index === 0 ? '' : ',\n') + JSON.stringify(row);
})
.to.stream(w, {columns: true, end: false})
.on('end', function() {
w.write(']');
w.end();
});
However the output from that script is created in this format:
[
{
"name": "crystal",
"description": "This is a crystal",
"price": "2.95"
},
{
"name": "emerald",
"description": "This is a emerald",
"price": "5.95"
}
]
How would I modify the script to get my desired "dictionary" format?
All you need to do is loop over the array and use item.name as key for your dictionary object
var products ={};
data.forEach(function(item){
products[item.name] = item;
});
This will leave the name property in the item but that shouldn't be an issue
I found csv parser library most useful:
var csvText=`status,path,name,ext,checksum,size,document_service_id,document_service_path,message
success,./15-02-2017_17-11/d77c7886-ffe9-40f2-b2fe-e68410d07891//expE1.txt,expE1.txt,txt,38441337865069eabae7754b29bb43e1,414984,8269f7e3-3221-49bb-bb5a-5796cf208fd1,/neuroinftest/20170215/expE1.txt,
success,./15-02-2017_17-11/d77c7886-ffe9-40f2-b2fe-e68410d07891//expE10.txt,expE10.txt,txt,f27e46979035706eb0aaf58c26e09585,368573,2c94ed19-29c9-4660-83cf-c2148c3d6f61,/neuroinftest/20170215/expE10.txt,
success,./15-02-2017_17-11/d77c7886-ffe9-40f2-b2fe-e68410d07891//expE2.txt,expE2.txt,txt,e1040d9546423c823944120de0e5c46c,333308,b3898f5d-1058-4cf3-acf9-76759117b810,/neuroinftest/20170215/expE2.txt,
`
var csv = require('csv');
csv.parse(csvText, {columns: true}, function(err, data){
console.log(JSON.stringify(data, null, 2));
});
In variable csvText I have my comma-separated file, with the first line serving as a header. I use the parse function and I'm passing the {columns: true} to indicated that the first line has the headers. Second parameter in the callback function (data) has the object with keys being the headers and the values being the corresponding csv cells. I use JSON.stringify to print it nicely and the result object looks like this (it puts it into an array):
[
{
"status": "success",
"path": "./15-02-2017_17-11/d77c7886-ffe9-40f2-b2fe-e68410d07891//expE1.txt",
"name": "expE1.txt",
"ext": "txt",
"checksum": "38441337865069eabae7754b29bb43e1",
"size": "414984",
"document_service_id": "8269f7e3-3221-49bb-bb5a-5796cf208fd1",
"document_service_path": "/neuroinftest/20170215/expE1.txt",
"message": ""
},
{
"status": "success",
"path": "./15-02-2017_17-11/d77c7886-ffe9-40f2-b2fe-e68410d07891//expE10.txt",
"name": "expE10.txt",
"ext": "txt",
"checksum": "f27e46979035706eb0aaf58c26e09585",
"size": "368573",
"document_service_id": "2c94ed19-29c9-4660-83cf-c2148c3d6f61",
"document_service_path": "/neuroinftest/20170215/expE10.txt",
"message": ""
},
{
"status": "success",
"path": "./15-02-2017_17-11/d77c7886-ffe9-40f2-b2fe-e68410d07891//expE2.txt",
"name": "expE2.txt",
"ext": "txt",
"checksum": "e1040d9546423c823944120de0e5c46c",
"size": "333308",
"document_service_id": "b3898f5d-1058-4cf3-acf9-76759117b810",
"document_service_path": "/neuroinftest/20170215/expE2.txt",
"message": ""
}
]
UPD: This array can easily be turned into the object you need with reduce:
var res_obj = data.reduce(function(acc, cur, i) {
acc[cur.name] = cur;
return acc;
}, {});
In my case I use the name property as a key. Make sure it's unique.
I think something like this would work :
var products_arr = [{"name":"crystal","description":"This is a crystal","price":"2.95"},
{"name":"emerald","description":"This is a emerald","price":"5.95"}]
var products = {};
for (var i = 0, l = products_arr.length ; i < l ; ++i) {
var x = products_arr[i];
var name = x.name
delete x.name; // deletes name property from JSON object
products[name] = x;
}
This will output :
{
"crystal": {
"description": "This is a crystal",
"price": "2.95"
},
"emerald": {
"description": "This is a emerald",
"price": "5.95"
}
}
If you would like to modify your specific code, you could change the line
return (index === 0 ? '' : ',\n') + JSON.stringify(row);
to
var clonedRow = JSON.parse(JSON.stringify(row));
var key = clonedRow['name'];
delete clonedRow['name'];
var newRow = {};
newRow[key] = clonedRow;
return (index === 0 ? '' : ',\n') + JSON.stringify(newRow);
This creates a new object for each row, modifying the structure according to your requirement.
Your best bet is to use PapaParse, a powerful csv parser/dumper. It supports streams, various string encodings, header row, and it's fast.

How to Push the values in the array, using jquery

Trying to push the values into temp Array, from the existing array object. Here am validating whether the values are null or not in my existing object and then pushing it into temp Array.
But currently this is output I am getting : ["0","abc"]
Expected output should be [{"0":"abc"},{"1":"def"}]
Once the values are pushed into the temp array, I need to bind it to my html list.
This is what have tried.
JS:
var tempArray = [];
var json = [
{
"itemId": "1",
"prodTitle": "abc",
},
{
"itemId": "2",
"prodTitle": "def",
},
{
"itemId": "",
"prodTitle": "",
}
]
for (var i=0;i<json.length;i++){
if(json[i].itemId!=""&&json[i].prodTitle!="")
tempArray.itemId = json[i].itemId;
tempArray.prodTitle = json[i].prodTitle;
tempArray.push(tempArray.itemId,tempArray.prodTitle);
}
console.log(tempArray);
Demo URL
You have many mistakes, here's right one
for (var i=0; i<json.length; i++){
if(json[i].itemId && json[i].prodTitle) {
tempArray.push(json[i]);
}
}
Your mistakes
for (var i=0;i<json.length;i++){
if(json[i].itemId!=""&&json[i].prodTitle!="") // <-- mistake, braces are needed, because you have 3 lines below
tempArray.itemId = json[i].itemId; // <-- you are adding property to array
tempArray.prodTitle = json[i].prodTitle; // <-- still adding
tempArray.push(tempArray.itemId,tempArray.prodTitle); //<-- pushing strings, not valid object, use like --> {key: value}
}
Another option using Array.filter Also makes it chain-able. However a for loop will be faster, depends if the chain-ability is something you require, i find it quite powerful at times.
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
var json = [
{
"itemId": "1",
"prodTitle": "abc",
},
{
"itemId": "2",
"prodTitle": "def",
},
{
"itemId": "",
"prodTitle": "",
}
];
var tempArray = json.filter(function (item) {
return (isDefined(item.itemId) && isDefined(item.prodTitle));
});
function isDefined (o) {
return o !== undefined && o !== null && o !== '';
}
console.log(tempArray);
http://jsfiddle.net/zgg79wfa/1/
You can achieve this without jQuery by using the .filter() method:
var json = [{
"itemId": "1",
"prodTitle": "abc",
},
{
"itemId": "2",
"prodTitle": "def",
},
{
"itemId": "",
"prodTitle": "",
}];
console.log( json );
var tempArray = json.filter( function( el ) {
return el.itemId && el.prodTitle;
});
console.log( tempArray );

Categories