How to iterate through array of objects and stringify - javascript

I've been at this for a bit trying to come up with a solution. I have tested a handful of stack solutions to iterate through nested objects but haven't gotten this to work correctly. My data structure is below.
I've been trying to first off iterate through nested objects which this stack seemed to be similar to mine.
Iterate through Nested JavaScript Objects
However, when I'm in my for loop getting access to geo, value object to grab all of its properties, ip, hostname, city etc I'm coming up empty handed with undefined. Here's a code snippet of what I've tried below.
I'm trying to take all of the keys and values in this entire object and stringify them into a beautiful parameter string to send over to the server in an ajax request.
for (var i = 0; i < myarray.length; i++) {
var o = myarray[i];
if (o.name === "geo") {
o.value.ip;
}
}
0: {name: "firstname", value: "John"}
1: {name: "lastname", value: "Smith"}
2: {name: "email", value: "asddas#gmail.com"}
3: {name: "password", value: "asdsdadasads"}
4: {name: "paypal_email", value: "asdsa#gmail.com"}
5: {name: "phone", value: "1234567894"}
6: {name: "geo",value: "
{"ip":"111.111.111.111","hostname":"rr.com","city":"MyCity","region":"Ohio","country":"US","loc":"41.34.23","org":"Inc","postal":"1234","timezone":"America/New_York","readme":"https://www.google.com"}"
__proto__: Object
length: 7
__proto__: Array(0)

The problem is that the structure of the geo object is odd:
name: "geo",value: "{"ip":"111.111.111.111","hostname":"rr.com","city":"MyCity","region":"Ohio","country":"US","loc":"41.34.23","org":"Inc","postal":"1234","timezone":"America/New_York","readme":"https://www.google.com"}"
The value looks to be a string in JSON notation. You'll have to parse it first in order to look up properties on it:
if (o.name === "geo") {
const nestedObj = JSON.parse(o.value);
console.log(nestedObj.ip);
}
You might also consider fixing whatever's serving you that object so that the value is an actual object - if that's possible (it may not be, but it would make the code make a lot more sense).
You can also consider using .find instead of a for loop, to make the code shorter and more elegant:
const json = myarray.find(({ name }) => name === 'geo').value;
const nestedObj = JSON.parse(json);
(if the geo object may not exist, test for undefined first, of course)

It would appear that the value field for the object with the name of "geo" is a JSON string.
Because the value is a string, you won't be able to directly access the ip field without first parsing that string to an object:
for (var i = 0; i < myarray.length; i++) {
var o = myarray[i];
if (o.name === "geo") {
/* "Convert" the JSON string in o.value to the corresponding object */
const valueObject = JSON.parse(o.value);
/* The ip field can now be accessed from the valueObject, parsed from
the JSON string in o.value */
console.log(valueObject.ip);
}
}

Related

Assigning K,V pairs to a JSON object in NodeJS

I have a NodeJS script that takes data from a source in the form of "key, value" pairs, and I would like to put that data into a JSON object.
I am using SNMP to get the k, v pairs, where the key is the OID. I would like to then map those values onto a JSON object without having to iteratively check each OID against a known value.
The k,v pairs are stored in objects as such, and I have no flexibility over this incoming data.
let pair = {
key: "abc...",
value: "xyz..."
}
I have defined the JSON object as an empty structure.
let jsonObject = {
ipaddress: "",
network: {
uptime: "",
throughput: "",
devices: ""
}
}
And I iterate through my keys (pairs is the name of an array containing the k,v objects)
for (let i = 0; i < pairs.length; i++) {
if (pairs[i].key == "1.2.3.4.5.6.7") jsonObject.ipaddress = pairs[i].value;
if (pairs[i].key == "2.3.4.5.6.7.8") jsonObject.network.uptime = pairs[i].value;
if (pairs[i].key == "3.4.5.6.7.8.9") jsonObject.network.devices = pairs[i].value;
}
I would like to know if there is any way to simplify this, as I have around 200 keys to process (the above code is simply an example), and it doesn't seem particularly well optimised for me to iterate over every possible key.
EDIT: The jsonObject is a lot more complex than shown here, with lots of layers and the names of the keys do not match up 1:1 with the json object property names as shown.
EDIT 2: This seems like an odd situation, I know.
For example, I want to take the K,V input:
Key Value
1.2.3.4.5.6 "10.0.0.1"
2.3.4.5.6.7 "3 Days 14 Hours 32 Minutes"
3.4.5.6.7.8 "1.1.1.1"
And convert it to a dissimilarly named JSON object
{
uptime: "3 Days 14 Hours 32 Minutes",
networking: {
ip: "10.0.0.1",
dns: "1.1.1.1"
}
}
Potentially using some form of mapping, instead of using ~200 if statements
Use the Array.prototype.reduce function.
const { name, ...properties } = pairs.reduce(
(obj, { key, value }) => Object.assign(obj, { [key]: value }),
{}
)
const obj = { name, properties }
Reduce will reduce an array into a scalar, in this case an object with all k,v pairs as fields with values on an object, starting with {} as a default value the merging each k,v pair 1 at a time.
Object.assign will merge objects, overwriting objects on the left with the fields of keys of objects on the right.
And finally the syntax to dynamically add a key on an object literal is { [k]: v }
By the way this is a useful trick for reducing the complexity of algorithms where you need to look up values in an array in a loop. Simply create an index of one array then in the loop, lookup in the index instead.
You can use Array.prototype.forEach for iterating and assigning the object.
const jsonObject = {
name: '',
properties: {
email: '',
address: '',
town: ''
}
};
const pairs = [{key: 'name', value: 'thatsimplekid'},
{key: 'email', value: 'aaa#domain.com'},
{key: 'town', value: 'myTown'},
{key: 'address', value:'123 main st' }];
pairs.forEach( ({key, value}) =>
jsonObject.hasOwnProperty(key) ?
jsonObject[key] = value :
jsonObject.properties[key] = value);
console.log(jsonObject);
for (let i = 0; i < pairs.length; i++) {
const key = pairs[i].key;
const value = pairs[i].value;
if (pairs[i].key == "name") {
jsonObject[key] = value;
} else {
jsonObject.properties[key] = value;
}
}
After the 'name' all values goes to the properties object, so a simple if would do it

Javascript array object arrays

THis is going to sound like a stupid question but here it goes. I have a js array formatted like so
var locationID = [
{ ID: "ID1", location: "location1" },
{ ID: "ID2", location: "location2" },
{ ID: "ID3", location: "location3" },
];
I am trying to loop through the array
for(i = 0; i < locationID.length;i++){
var object = locationID[i];
}
I want to get both elements from the inner array so the ID and location. would I do this by object[0] or object["ID"] for example.
Also is there a more efficient way to do what I need to do like a for each loop or something along those lines.
Use object.ID or object['ID'].
Objects {} in JavaScript are associative, or named arrays. (Also known as a map in many languages. They are indexed by strings (in this case).
Arrays [], are indexed by integral numbers, starting from 0 and counting up to n-1, where n is the length of the array.
If you want to programmatically go through all the (key, value) pairs in each object, you can use this method.
Quotations (String Literals)
To reiterate my comment below about single and double quotes:
If you're talking about inside the [], no [,they're not important]. JavaScript treats single
quotes and double quotes pretty much the same. Both of them denote
string literals. Interestingly, you can use single quotes inside
double quotes or vice-versa: "I wanted to say 'Hello world!'" would be
a (single) valid string, but so would 'But I accidentally said "Goodbye".
This is an optimized loop based from the book of Nicholas Zackas (YAHOO performance chief). I am performing a cached array length to prevent re-evaluation of array length on every iteration of the loop. Please check jsperf.com. Also, native loop is always faster than method based loops jQuery.each and Array.prototype.forEach. This is also supported on browsers below ie8
var currentItem,
locationInfo = [
{ ID: "ID1", location: "location1" },
{ ID: "ID2", location: "location2" },
{ ID: "ID3", location: "location3" },
];
for (var i = 0, len = locationInfo.length; i < len; i++) {
currentItem = locationInfo[i];
console.log(currentItem.ID);//I prefer this because it shrinks down the size of the js file
console.log(currentItem["ID"]);
}
what you have already will return each of the objects in the JSON as you run the loop. What you need is something like
for(i = 0; i < locationID.length;i++){
var object = {locationID[i].ID, locationID[i].location};
}
Remember properties of objects are accessed by their keys since they are key-value pairs.
For loops are going to be your best bet as far as speed, here's how you'd do it with forEach (IE 9+)
locationID.forEach(function(location, i){
console.log(location['ID'])
console.log(location['location'])
});
jQuery make's it a little easier but runs slower
$.each(array, function(i, item){
});
http://jsperf.com/for-vs-foreach/75
Also here a useful link: For-each over an array in JavaScript?
You can use the forEach method, which make your code more cleaner.
See forEach
locationID.forEach(function(elm){
//Here, elm is my current object
var data = elm;
console.log(data.ID):
console.log(data.location);
});
EDIT :
Then for your second question, you should filter and map methods.
function findNamebyID(id){
//Filter by id and map the data to location
return locationID.filter(function(elm){
return elm.ID === id;
}).map(function(elm){
return elm.location;
})
}
Something as:
var location = locationID.reduce(function(ob, cur) {
ob[cur.ID] = cur.location;
return ob;
}, {});
The result you get is:
Object {ID1: "location1", ID2: "location2", ID3: "location3"}
Meaning you can do:
location.ID1 // location1
location.ID2 // location2
...
an alternative to your loop, would be to use the JavaScript for (.. in ..) since you aren't really using the iterator; it just adds fluff
for(i = 0; i < locationID.length;i++){
var object = locationID[i];
}
could be written as:
for (item in locationID) {
var object = item;
}

Add item to array by key in JavaScript

I need to group item having same name property and increase their number. I try to assign to new array and check existed item by key. It works fine when I use this solution in PHP, but in JavaScript it doesn't.
I have searched some similar questions, but I don't know why it doesn't work.
var orgArr = [
{name: 'abc', number: 3},
{name: 'xyz', number: 2},
{name: 'abc', number: 5}
];
var result = []; //work if result = {};
for (var i = 0; i < orgArr.length; i++) {
if (!result[orgArr[i].name]) {
result[orgArr[i].name] = orgArr[i]; //assign new
} else {
result[orgArr[i].name].number += orgArr[i].number; //increase number if name exist in result array
}
}
alert(JSON.stringify(result)); //expect array 2 item but it's empty array
console.log(result); //Will have result 2 item when I view console window
var orgArr = [
{name: 'abc', number: 3},
{name: 'xyz', number: 2},
{name: 'abc', number: 5}
];
var result = []; //work if result = {};
var tempArray = []; // used to store unique name to prevent complex loop
orgArr.forEach(function(item){
if($.inArray(item.name, tempArray)< 0){// unique name
result.push(item);
tempArray.push(item.name);
}
else{
var indexNew = $.inArray(item.name, tempArray);
result[indexNew].number += item.number;
}
});
alert(JSON.stringify(result)); //expect array 2 item but it's empty array
console.log(result); //Will have result 2 item when I view console window
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
E/ My previous answer was incorrect.
Well.. yes...
[] designates an array. An array holds everything by integer values. You're trying to feed it a string value (orgArr[x].name) and since its just an array, it discards it as a bad call.
{} is an object. Objects can have string indexes.
var result = []; //work if result = {};
Why can't result be {}?
if you want it to work, make result = {} not []
an array is not a key value store. It still will take key values, and will store them on the array object. But when stringify encounters your array, it determines it is an array and then trys to iterate the array, and your array appears empty. so you get nothing in your output.
You get empty array it's because by default JSON.stringify failed to convert your array to json string.
By default JSON.stringify converts int-based index array to json string but you are using orgArr[i].name which is a string as array index that the cause alert() show empty array.
Can you explain why would you want to convert json array to an array with string index. It's always better to use json array if you want a string as key/index.
For more information about JSON.stringify

Converting JSON to array key - value in javascript

I've been developing a web application where I'm receiving data in this format, from a node server:
"{""elements":[{"10sr2b2":{"total":0,"bad":22,"clients":["fc8e7f","fc8e7e"],"zone":"101900"}}]}"
The poblem is this data is an array key-value called "elements" where "10sr2b2" is the key of the first element of the array.
So when I call $.parseJSON() method, this return an object like this:
elements: Array[1]
0: Object
10sr2b2: Object
zone: "101900"
clients: Array[2]
0: "fc8e7f"
1: "fc8e7e"
length: 2
__proto__: Array[0]
bad: 22
total: 0
Where "10sr2b2" it's supposed to be the key and it's an object and I need to get this value somehow.
Can you help me?
You could use Object.keys to get the object keys.
var keys = Object.keys(data.elements[0]);
Can you change the format from the node server? It needs to send something more like:
"{""elements":[{"key": "10sr2b2" "value": {"total":0,"bad":22,"clients":"fc8e7f","fc8e7e"],"zone":"101900"}}]}"
If you know you'll always only have one key for each item, you can use a for..in loop that immediately breaks, for example
var i, key, obj = $.parseJSON(/*...*/);
for (i = 0; i < obj.elements.length; ++i) { // loop over elements
for (key in obj.elements[i]) break; // get key
// now can access
obj.elements[i][key]; // Object
}

Confuse about array and object in node.js

I have a array for store object, which have an object in it already:
var obj = [{
name: 'json',
lang: 'en'
}];
console,.log(obj) //the result is OK;
then I want push another object into it, just like:
var newObj = {
name: 'lee',
lang: 'zh'
}
obj.push(newObj)
but after this I print the obj array,console.log(obj), the result is 2 !!
Why this happen? How can I solve this problem?To store object in array correctly
Make sure you didn't do obj = obj.push(newObj);, because .push method returns the number of elements after push; instead, the line should simply read obj.push(newObj).

Categories

Resources