How to convert Json into associative array or key value array - javascript

I have following Json which i need to insert into a table.
I want to convert each student detail into a row.
Because if i loop through the rows as per the existing structure i am reading one column as a row.
var json {
"Students":[
{
"name":{
"value":"Allan"
},
"number":{
"value":"123"
}
},
{
"name":{
"value":"Frank"
},
"number":{
"value":"456"
}
}
]
}
Ideally i want to the above as
{ "name": "Allan", "number": 123};
{ "name": "Frank", "number": 456};
I am looping through the Json as below
var objectKeys = Object.keys(json);
for (var key in objectKeys)
{
var student = json.Students;
for (var i = 0; i < student .length; i++) {
for (var column in json.Students[i]) {
window.print(column);
window.print(json.Students[i][column].value);
}
}
}
NOTE: No JQuery, want to achieve the above through normal Javascript.

If you want to transform the data, you can use Array.map
var json = {"Students":[{"name":{"value":"Allan"},"number":{"value":"123"}},{"name":{"value":"Frank"},"number":{"value":"456"}}]};
let result = json.Students.map(o => ({
name: o.name.value,
number: o.number.value
}));
console.log(result);
If you want to access the data, you can use Array.forEach
var json = {"Students":[{"name":{"value":"Allan"},"number":{"value":"123"}},{"name":{"value":"Frank"},"number":{"value":"456"}}]};
json.Students.forEach(o => console.log({name: o.name.value, number: o.number.value}));

var json = {
"Students":[
{
"name":{
"value":"Allan"
},
"number":{
"value":"123"
}
},
{
"name":{
"value":"Frank"
},
"number":{
"value":"456"
}
}
]
}
var studentData = JSON.stringify(json.Students);
var convertedData = JSON.parse(studentData.replace(/\{\"value\"\:/g,"").replace(/\}\,\"number/g,',"number').replace(/\"\}\}/g,'"}'));
Try this :)

No map or reduce. Just classic Javascript.
var json = {
"Students": [{
"name": {
"value": "Allan"
},
"number": {
"value": "123"
}
},
{
"name": {
"value": "Frank"
},
"number": {
"value": "456"
}
}
]
};
for (var student of json["Students"]) {
console.log(student); //your logic goes here.
}

Related

Build array from another array if some key are identical using JavaScript

I have an array of data. Some of the key in the array are same. I would like to create a new array based on the key and add the other data.
This is my array
var myObjOne = [
{
"name":"John",
"id":1,
"car":"maruti"
},
{
"name":"John",
"id":2,
"car":"wolks"
},
{
"name":"John",
"id":3,
"car":"bmw"
},
{
"name":"Peter",
"id":4,
"car":"alto"
},
{
"name":"Peter",
"id":5,
"car":"swift"
}
];
I would like to convert the array in to the below format.
var myObj = [
{
"name":"John",
"items": [
{ "id":1, "car":"maruti" },
{ "id":2, "car":"wolks" },
{ "id":3, "car":"bmw" }
]},
{
"name":"Peter",
"items": [
{ "id":4, "car":"alto" },
{ "id":5, "car":"swift" },
]
}
];
I am working on a node environment.
You can create an object using Array#reduce first which maps name with items, and then create the final array by looping over the intermediate map using a for...of loop:
var source = [{"name":"John","id":1,"car":"maruti"},{"name":"John","id":2,"car":"wolks"},{"name":"John","id":3,"car":"bmw"},{"name":"Peter","id":4,"cars":"alto"},{"name":"Peter","id":5,"cars":"swift"}];
const map = source.reduce((acc, {name, ...obj}) => {
if (!acc[name]) {
acc[name] = [];
}
acc[name].push(obj);
return acc;
}, {});
const result = [];
for (let[name, items] of Object.entries(map)) {
result.push({name, items});
}
console.log(result);
Array.reduce is at rescue.This method accepts an accumulator and current
item. Check in the accumulator if there exist an object where the value of name property is John or Peter
var myObjOne = [{
"name": "John",
"id": 1,
"car": "maruti"
},
{
"name": "John",
"id": 2,
"car": "wolks"
},
{
"name": "John",
"id": 3,
"car": "bmw"
},
{
"name": "Peter",
"id": 4,
"car": "alto"
},
{
"name": "Peter",
"id": 5,
"car": "swift"
}
];
var newObj = myObjOne.reduce(function(acc, curr, currIndex) {
// using findIndex to check if there exist an object
// where the value of the name property is John, Peter
// if it exist it will return the index else it will return -1
let ifNameExist = acc.findIndex(function(item) {
return item.name === curr.name;
})
// if -1 then create a object with name and item property and push
// it to the accumulator
if (ifNameExist === -1) {
let nameObj = {};
nameObj.name = curr.name;
nameObj.items = [];
nameObj.items.push({
id: curr.id,
car: curr.car
})
acc.push(nameObj)
} else {
// if such an object already exist then just update the item array
acc[ifNameExist].items.push({
id: curr.id,
car: curr.car
})
}
return acc;
}, []);
console.log(newObj)
Use .reduce to group by name, and use .find inside the reducer to find if the matching name has already been added:
const input=[{"name":"John","id":1,"car":"maruti"},{"name":"John","id":2,"car":"wolks"},{"name":"John","id":3,"car":"bmw"},{"name":"Peter","id":4,"cars":"alto"},{"name":"Peter","id":5,"cars":"swift"}]
const output = input.reduce((a, { name, ...item }) => {
const foundNameObj = a.find(nameObj => nameObj.name === name);
if (foundNameObj) foundNameObj.items.push(item);
else a.push({ name, items: [item] });
return a;
}, []);
console.log(output);

Calculate object property values based on user id

Got an object containing a user id for each user and prices, would like to create a new object/array for each user (no duplicates) and be able to calculate the total sum of price for each user. Tried using Object.values() with map and filter but can't get it to work properly
{
"data": {
"item1": {
"price": "20",
"user": "user1"
},
"item2": {
"price": "10",
"user": "user2"
},
"item3": {
"price": "50",
"user": "user1"
}
}
}
Output something like this:
{
"users": {
"user1": {
"totalSum": "70",
},
"user2": {
"totalSum": "10",
}
}
}
I'm thinking about using map to present the "users"-data, maybe an array would be better?
Using function reduce.
Important: The attribute price is a String, this approach uses object Number to convert that value to a numeric one.
var obj = { "data": { "item1": { "price": "20", "user": "user1" }, "item2": { "price": "10", "user": "user2" }, "item3": { "price": "50", "user": "user1" } }};
var result = Object.keys(obj.data).reduce((a, k) => {
if (a.users[obj.data[k].user]) {
a.users[obj.data[k].user].totalSum += Number(obj.data[k].price);
} else {
a.users[obj.data[k].user] = {
"totalSum": Number(obj.data[k].price)
}
}
return a;
}, {
'users': {}
});
console.log(result);
.as-console-wrapper {
max-height: 100% !important; top: 0;
}
You could leverage ```reduce, more information here
code (haven't tried this)
var data = JSON.parse(mainObj).data;
var usersWithTotalExpenditure = Object.keys(data).reduce(function(result, key) {
var currentItem = data[key];
var useName = currentItem.user;
var price = Number(currentItem.price);
if (userName in result) {
result[userName].totalSum += price;
} else {
result[userName] = {
totalSum: price
};
}
return result;
}, {});
var resultObject = {
users: usersWithTotalExpenditure
}
You can use a forEach loop. This relies on Javascripts powerful OR operator, which coerces the first half of the expression to false if the current user's price is not defined (meaning it is a user the loop hasn't encountered before)
`c is your initial object's data, output is empty object`
const c = obj.data;
var output = {};
Object.keys(c).forEach((val) => {
output[c[val]["user"]] = parseInt(output[c[val]["user"]]) + parseInt(c[val]["price"]) || parseInt(c[val]["price"]);
})

how to add an element inside a json array at the specific index in a repeating block?

I am trying to add element "delete:true" after each occurrence of "_rev " mentioned in the below sample request.
Original Request:
{
"docs": [
{
"_id": "123",
"_rev": "1-7836",
},
{
"_id": "456",
"_rev": "1-1192",
}
]
}
Expected Request:
{
"docs": [
{
"_id": "123",
"_rev": "1-7836",
"_deleted" :true
},
{
"_id": "456",
"_rev": "1-1192",
"_deleted" :true
}
]
}
When I tried the below code,the ""_deleted" :true" is getting inserted after the -rev element is closed. PFB for the same and suggest.
function main(params) {
for (var i = 0; i< params.docs.length; i++) {
for (var value in params.docs[i]) {
if(value == '_rev' && params.docs[i]._rev ){
var string1 = JSON.stringify(params.docs[i]);
var str = ',';
var string2 = '"';
var string3 =str+string2+ '_deleted'+ string2+ ':' + "true" ;
var res = string1 + string3 ;
}
}
}
}
######################
[
"2018-01-23T09:44:23.568738362Z stdout:
{\"_id\":\"123\",
\"_rev\":\"1-7836\"},
\"_deleted\":true"]
Use map and Object.assign instead of generating a string
var output = params.docs.map( s => Object.assign( {}, {"_deleted" :true}, s ) );
You can then convert this to string using JSON.stringify( output );
Demo
var params = {
"docs": [{
"_id": "123",
"_rev": "1-7836",
},
{
"_id": "456",
"_rev": "1-1192",
}
]
};
var output = params.docs.map(s => Object.assign({}, {
"_deleted": true
}, s));
console.log(output);
var data = {
"docs": [
{
"_id": "123",
"_rev": "1-7836",
},
{
"_id": "456",
"_rev": "1-1192",
}
]
}
var newData = data['docs'].map(item => {
item._delete = true
return item
})
console.log(newData);
Why don't you simply put ._deleted attribute to doc, like this ?
function main(params) {
for (var i = 0; i< params.docs.length; i++) {
params.docs[i]._deleted = true;
var res = JSON.stringify(params.docs[i]);
}
}
}
Or like this :
function main(params) {
for (var i = 0; i< params.docs.length; i++) {
params.docs[i]["_deleted"] = true;
var res = JSON.stringify(params.docs[i]);
}
}
}
You can reference the not existing attribute directly and assign an value:
#!/usr/bin/js
var myJSON = { "docs": [ { "_id":"123", "_rev":"1-200" } ] }
console.log(myJSON);
myJSON.docs[0]["_deleted"]=true;
console.log(myJSON);
Output of example:
# js append.js
{ docs: [ { _id: '123', _rev: '1-200' } ] }
{ docs: [ { _id: '123', _rev: '1-200', _deleted: true } ] }
Read the more extensive example here: Add new attribute (element) to JSON object using JavaScript
So this might be a duplicate ...

How to add a new key to multiple indices of an array of objects?

I've got an array of three people. I want to add a new key to multiple objects at once based on an array of indices. Clearly my attempt at using multiple indices doesn't work but I can't seem to find the correct approach.
var array = [
{
"name": "Tom",
},
{
"name": "Dick",
},
{
"name": "Harry",
}
];
array[0,1].title = "Manager";
array[2].title = "Staff";
console.log(array);
Which returns this:
[
{
"name": "Tom",
},
{
"name": "Dick",
"title": "Manager"
},
{
"name": "Harry",
"title": "Staff"
}
]
But I'd like it to return this.
[
{
"name": "Tom",
"title": "Manager"
},
{
"name": "Dick",
"title": "Manager"
},
{
"name": "Harry",
"title": "Staff"
}
]
You cannot use multiple keys by using any separator in arrays.
Wrong: array[x, y]
Correct: array[x] and array[y]
In your case, it will be array[0].title = array[1].title = "manager";
1st method::
array[0].title = "Manager";
array[1].title = "Manager";
array[2].title = "Staff";
array[0,1] will not work.
2nd method::
for(var i=0;i<array.length;i++) {
var msg = "Manager";
if(i===2) {
msg = "Staff"
}
array[i].title = msg
}
You can use a helper function like this
function setMultiple(array, key, indexes, value)
{
for(i in array.length)
{
if(indexes.indexOf(i)>=0){
array[i][key] = value;
}
}
}
And then
setMultiple(array, "title", [0,1], "Manager");
Try this: `
for (var i=0; var<= array.length; i++){
array[i].title = "manager";
}`
Or you can change it around so var is less than or equal to any n range of keys in the index.
EDIT: instead make var <= 1. The point is to make for loops for the range of indices you want to change the title to.
Assuming that you have a bigger set of array objects.
var array = [
{
"name": "Tom",
},
{
"name": "Dick",
},
{
"name": "Harry",
},
.
.
.
];
Create an object for the new keys you want to add like so:
let newKeys = {
'Manager': [0,2],
'Staff': [1]
}
Now you can add more such titles here with the required indexes.
with that, you can do something like:
function addCustomProperty(array, newKeys, newProp) {
for (let key in newKeys) {
array.forEach((el, index) => {
if (key.indexOf(index) > -1) { // if the array corresponding to
el[newProp] = key // the key has the current array object
} // index, then add the key to the
}) // object.
}
return array
}
let someVar = addCustomProperty(array, newKeys, 'title')

js loop after a certain json node

I'm trying to loop through some json nodes after finding a specific json node.
So, here's the INPUT:
{
"search": {
"result": {
"DN": {
"$": "A,B,C"
},
"attribute-value": [
{
"#name": "name",
"$": "nameHere"
},
{
"#name": "account",
"$": "accountNameHere"
},
{
"#name": "role",
"$": "roleA"
},
{
"#name": "role",
"$": "roleB"
}
]
}
}}
As you can see there are 2 roles at the end of the json payload above.
So, I get to that #name = role with the following logic:
var attributeValue = node['search'].result['attribute-value'];
for (var i = 0; i < attributeValue.length; i++) {
if (attributeValue[i]['#name'] === 'role') {
var vRole = attributeValue[i].$;
//The newJson.roles.role is to assign it to the new payload below
newJson.roles.role = vRole;
}
}
Once I get there, I'd like to pick up both roleA and roleB and output it into the following newJson payload:
var newJson = {
"newJson": {
"roles": [{
"role": {}
}, {
"role": {}
}],
}
}
The goal is to be able to get all the INPUT role nodes and output it in the newJson payload, but when I attempt to issue a for loop after getting to that #name=role, it fails.
Any suggestion is well appreciated.
Thank you.
I think you should append a new object to the roles array, just like this in your for loop:
var attributeValue = node['search'].result['attribute-value'];
for (var i = 0; i < attributeValue.length; i++) {
if (attributeValue[i]['#name'] === 'role') {
var vRole = attributeValue[i].$;
newJson.roles.push({
role: vRole
});
}
}
Hope this can help
Try this:
var attributeValue = node['search'].result['attribute-value'];
var newJson = {roles:[]};
attributeValue.forEach(function(item){
if(item["#name"]==="role"){
newJson.roles.push({role:item["$"]})
}
});
console.log(JSON.stringify(newJson));
You can use filter and map array methods.
newJson.roles = attributeValue
.filter(function(x){return x['#name']==='role'})
.map(function(x){return {'role': x['$']}})
Thanks everyone - you're all awesome!
This worked out for me:
JSBIN
var d = {
"search": {
"result": {
"DN": {
"$": "A,B,C"
},
"attribute-value": [
{
"#name": "name",
"$": "nameHere"
},
{
"#name": "account",
"$": "accountNameHere"
},
{
"#name": "role",
"$": "roleA"
},
{
"#name": "role",
"$": "roleB"
}
]
}
}};
var newJson = {
"newJson": {
"roles": []
}
};
var attributeValue = d.search.result['attribute-value'];
for (var i = 0; i < attributeValue.length; i++) {
if (attributeValue[i]['#name'] === 'role') {
var vRole = attributeValue[i].$;
newJson.newJson.roles.push({"role": vRole});
}
}
console.log(newJson);
~~~~~~~~~~~~~~~~~~~~~ final result ~~~~~~~~~~~~~~
[object Object] {
newJson: [object Object] {
roles: [[object Object] {
role: "roleA"
}, [object Object] {
role: "roleB"
}]
}
}

Categories