Create a nested JSON object dynamically - javascript

(context)I have information from a bunch of elements that I'm collecting into a JSON object that then gets passed down to an MVC3 controller where it gets deserialized into an object.
There are 'items' and 'item settings'. Currently, I have have both items and item settings all in flat JSON object. Ideally I would like to have the item settings nested under each item. My code currently looks like this:
var editeditems=[];
...
$("#SaveChanges").click(function() {
//this works and retrieves all of the item IDs
$(".portlet").each(function() {
var itemname = $(this).data("itemname");
editeditems.push(
{
"itemname": itemname
});
itemname = $(this).data("itemname");
$(".settingInput").each(function() {
editeditems.push(
{
"settingkey":$(this).attr("name"),
"settingvalue":$(this).attr("value")
});
});
});
Under the $(".settingInput").each function is where the settings get added. I've tried syntax like 'editedItems.settings.push..' but it returns with a syntax error.
Any help would greatly be appreciated!

var editeditems = [];
...
$('#SaveChanges').click(function() {
$('.portlet').each(function() {
var settings = [];
$('.settingInput').each(function() {
settings.push({
settingkey: $(this).attr('name'),
settingvalue: $(this).attr('value')
});
});
editeditems.push({
itemname: $(this).data('itemname'),
settings: settings
});
});
...
});
will generate sample output:
var editeditems =
[
{
"itemname": "item1",
"settings": [
{
"settingkey": "key1",
"settingvalue": "value1"
},
{
"settingkey": "key2",
"settingvalue": "value2"
}
]
},
{
"itemname": "item2",
"settings": [
{
"settingkey": "key1",
"settingvalue": "value3"
},
{
"settingkey": "key2",
"settingvalue": "value4"
}
]
}
];

var ei = {'settings': [3]};
ei.settings.push(4);
console.log(ei);
// This will output an object with property settings and value an array with values (3 and 4)

You need to create flat data array json as:
[{"itemname": "item1","settingkey": "key1","settingvalue": "value1"},
{"itemname": "item2","settingkey": "key2","settingvalue": "value2"},];
Than process the above date like this
var keys = Object.keys(dataMap);
var json = [];
for (var key in keys) {
var innerJson = {};
innerJson["name"] = keys[key];
var innerMap = dataMap[keys[key]];
if (innerMap instanceof Array) {
innerJson["size"] = innerMap[0];
} else if (innerMap instanceof Object) {
var child = processHirarchiachalData(innerMap);
innerJson["children"] = child;
}
json.push(innerJson);
}

Related

How to convert array of model objects to object with model ids as keys?

In Javascript I have an array of model objects:
[
{
"id":13,
"title":"Some title 1",
"time": "friday"
...
},
{
"id":15,
"title":"Some title 3",
"time": "Saturday"
...
},
{
"id":16,
...
},
...
]
(there is more than 2 values and properties on each object)
I want to get an object with each id from the array moved to key, like so:
{
13: {
title: "Some title 1",
time: "Friday"
...
},
15: {
title: "Some title 3",
time: "Saturday"
...
},
16: {
...
},
...
}
I am producing the array with Rails view .to_json include: {} syntax, so an answer in rails would also work for me. I will use the result object with Redux for an initial state so some kind of Redux answer is great too. Also would be interested in both es6 and es5 answer (I will use es5 answer though because Rails doesn't compile es6 in views, but later we are porting to client side application where it would also apply).
The simplest solution is to iterate over the array and attach a copy of each item to a new object:
let result = {};
for (let item of data) {
let newObject = Object.assign({}, item);
result[newObject.id] = newObject;
delete newObject.id;
}
If you don't need the data array later on it gets even simpler:
let result = {};
for (let item of data) {
result[item.id] = item;
delete item.id;
}
A simple way would be to just iterate through the array in Ruby:
foo = [
{
"id":13,
"title":"Some title 1",
...
},
{
"id":15,
"title":"Some title 3",
...
}]
result = {}
foo.each {|f| result[f.delete('id')] = f}
You can use reduce() to create object and inside you can loop object properties with Object.keys() and forEach() loop to create inner objects.
var data = [{
"id": 13,
"title": "Some title 1",
'lorem': 'ipsum'
}, {
"id": 15,
"title": "Some title 3",
}, {
"id": 16,
}]
var result = data.reduce(function(r, e) {
r[e.id] = {}
Object.keys(e).forEach(function(k) {
if(k != 'id') r[e.id] = Object.assign(r[e.id], {[k]: e[k]})
})
return r
}, {})
console.log(result)
Another approach is to use reduce() two times. First one to create one outer object and inner reduce to create each object inside first object.
var data = [{"id":13,"title":"Some title 1","lorem":"ipsum"},{"id":15,"title":"Some title 3"},{"id":16}]
var result = data.reduce(function(r, e) {
r[e.id] = Object.keys(e).reduce(function(o, a) {
if(a != 'id') o[a] = e[a]
return o;
}, {})
return r;
}, {})
console.log(result)
Use below code
try {
JSONArray jsonArray=new JSONArray("yourJsonString");
for(int i=0;i<jsonArray.length();i++){
JSONObject outer_jsonObject=new JSONObject();
JSONObject inner_jsonObject=new JSONObject();
inner_jsonObject.put("title",jsonArray.getJSONObject(i).getString("title"));
outer_jsonObject.put(jsonArray.getJSONObject(i).getString("id"),inner_jsonObject);
}
} catch (JSONException e) {
e.printStackTrace();
}
I would suggest you following approach.
For every id, assign an object with titles key, holding an array of titles as it's value.
It looks clean and it's easily readable, especially when there's few titles for one id.
var arr=[{id:13,title:"Some title 1"},{id:15,title1:"Some title 3",title2:"Some title 4"},{id:16}], result = [];
arr.forEach(function(v){
var obj = {};
var titles = {};
var titlesArr = [];
Object.keys(v).forEach(function(c){
if (c != 'id') {
titlesArr.push(v[c]);
titles.titles = titlesArr;
}
});
obj.id = titles;
result.push(obj);
});
console.log(result);
return users.reduce((results, u)=> (results[u.id] = u, results), {})

Pushing Javascript Object Inside An Array Using A For Loop

Hi I am trying push a javascript object inside an array in javascript using a for loop to iterate through the data. Here is how my code looks like.
var data = {"up": [{
"name": "jack",
"age" : 10
},
{
"name" : "jhon",
"age" : 12
}]};
var output = {};
var output_data = {
element: []
};
for (var key in data.up) {
output.user_name = data.up[key].name;
output_data.element.push(output);
}
console.log(output_data.element);
However as you can see in the example http://jsbin.com/fanazaxoda/edit?html,js,console only the second element is name 'jhon' is inserted in both occations. What am I doing wrong here? Please explain.
Move the output initialization inside for loop otherwise it push reference of object each time. Updating it's property may reflect in all array elements since all elements are referring the same object.
var output_data = {
element: []
};
for (var key in data.up) {
var output = {}; // create new empty object on each iteration
output.user_name = data.up[key].name;
output_data.element.push(output);
}
var data = {
"up": [{
"name": "jack",
"age": 10
}, {
"name": "jhon",
"age": 12
}]
};
var output_data = {
element: []
};
for (var key in data.up) {
var output = {};
output.user_name = data.up[key].name;
output_data.element.push(output);
}
console.log(output_data.element);

Merging unassociated array with serialized name/value pairs

Other than just iterating over the unassociated array and manually adding them, how does one merge an unassociated array with serialized name/value pairs?
//I select some values
var data = $('#mytable input:checked');
console.log(data); //Object[input attribute value = "1", input attribute value = "3"]
//I get some extra values I wish to send to the server
var types = data.map(function() {
return $(this).data("types");
}).get();
console.log(types); // ["type1", "type3"]
//I serialize data
data = data.serializeArray();
console.log(data); // [Object { name="id[]", value="1"}, Object { name="id[]", value="3"}]
//I add an extra value
data.push({
name: "task",
value: 'restoreRecord'
})
console.log(data); // [Object { name="id[]", value="1"}, Object { name="id[]", value="3"}, Object { name="task", value="restoreRecord"}]
/*
How do I merge data and types so that I come up with the following:
[
Object { name="id[]", value="1"},
Object { name="id[]", value="3"},
Object { name="types[]", value="type1"},
Opject { name="types[]", value="type3"},
Object { name="task", value="restoreRecord"}
]
*/
You can run a for loop over types and add values from it to data
// I want to merge this
var data = [{
name: "id[]",
value: "1"
}, {
name: "id[]",
value: "3"
}, {
name: "task",
value: "restoreRecord"
}];
// with this
var types = ['type1', 'type2'];
for(var i = 0; i < types.length; i++){
data.push({
name: 'types[]',
value: types[i]
});
}
console.log(data);

How to iterate over this json String

In this fiddle attempting to iterate over json String :
http://jsfiddle.net/sfbanvv6/2/
But receive exception :
Uncaught SyntaxError: Unexpected token e
JSON is valid ? So something incorrect with how I'm iterating ?
fiddle code :
javascript :
jQuery(document).ready(function() {
var jsonString2 = '{ "header": "test1", "children": [ { "date": "2015-01-02", "count": "36" }, { "date": "2015-01-03", "count": "29" } ] }'
var data2 = []
var combinedHeights2=[]
var myData2 = JSON.parse(jsonString2);
$.each(myData2, function(i, obj) {
console.log($.parseJSON(obj))
$.each(obj.children, function(i2, obj2) {
console.log('here')
var d = new Date(obj2.date)
console.log(Date.parse(d))
// data2.push([Date.parse(d), parseInt(obj.count)])
// combinedHeights2.push(parseInt(obj.count))
});
});
});
$.parseJSON(obj) is attempting to parse something that is already parsed. JSON parsers don't parse only the top level and leave the inner JSON as JSON, they return an entire nested set of arrays and objects. So your error may be caused by your logging code.
The cure is to recognize that obj doesn't need any parsing and you can just use it directly.
Getting more specific, this code will do what you seem to want:
var jsonString2 = '{ "header": "test1", "children": [
{ "date": "2015-01-02", "count": "36" },
{ "date": "2015-01-03", "count": "29" }
] }';
var data2 = [];
var combinedHeights2 = [];
var myData2 = JSON.parse(jsonString2);
console.log(myData2);
$.each(myData2.children, function(i, obj) {
console.log(obj);
var d = new Date(obj.date);
console.log(Date.parse(d));
});
Especially pay attention to what myData2 looks like when logged. You need to use myData2.children in your each, not myData2 by itself.
P.S. Get some semicolons!
With chrome logging formats you can more clearly see what you are iterating with by changing your logging statement to;
$.each(myData2, function(i, obj) {
console.log('%s %O', i, obj);
});
Your first obj is property in the loop header = 'test1' there is no children property for this. The second is children = [ ] which is your array.
To iterate over the array just use;
$.each(myData2.children, function(i, obj) {
var d = new Date(obj.date)
}
obj.children was undefined. Here its the working one
var myData2 = JSON.parse(jsonString2);
$.each(myData2, function(i, obj) {
var t = myData2.children;
$.each(t, function(i2, obj2) {
console.log(obj2);
//var d = new Date(obj2.date);
//console.log(Date.parse(d));
// data2.push([Date.parse(d), parseInt(obj.count)])
// combinedHeights2.push(parseInt(obj.count))
});
});
but here is a better version to get only dates
$.each(myData2.children, function(i, obj) {
var t = this;
console.log(t.date);
var d = new Date(t.date);
});
});
If you are trying to iterate the children property of your Json then you can do it this way:
jQuery(document).ready(function() {
var jsonString2 = '{ "header": "test1", "children": [ { "date": "2015-01-02", "count": "36" }, { "date": "2015-01-03", "count": "29" } ] }'
var myData2 = JSON.parse(jsonString2);
$.each(myData2.children, function(i, obj) {
console.log(obj);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
You were getting the exception because your code tried to iterate over your "header" parameter which holds a String and therefor cannot be iterated.

JSON data transformation from table-like format to JSON?

I have data that's in this format:
{
"columns": [
{
"values": [
{
"data": [
"Project Name",
"Owner",
"Creation Date",
"Completed Tasks"
]
}
]
}
],
"rows": [
{
"values": [
{
"data": [
"My Project 1",
"Franklin",
"7/1/2015",
"387"
]
}
]
},
{
"values": [
{
"data": [
"My Project 2",
"Beth",
"7/12/2015",
"402"
]
}
]
}
]
}
Is there some super short/easy way I can format it like so:
{
"projects": [
{
"projectName": "My Project 1",
"owner": "Franklin",
"creationDate": "7/1/2015",
"completedTasks": "387"
},
{
"projectName": "My Project 2",
"owner": "Beth",
"creationDate": "7/12/2015",
"completedTasks": "402"
}
]
}
I've already got the column name translation code:
r = s.replace(/\%/g, 'Perc')
.replace(/^[0-9A-Z]/g, function (x) {
return x.toLowerCase();
}).replace(/[\(\)\s]/g, '');
Before I dive into this with a bunch of forEach loops, I was wondering if there was a super quick way to transform this. I'm open to using libraries such as Underscore.
function translate(str) {
return str.replace(/\%/g, 'Perc')
.replace(/^[0-9A-Z]/g, function (x) {
return x.toLowerCase();
})
.replace(/[\(\)\s]/g, '');
}
function newFormat(obj) {
// grab the column names
var colNames = obj.columns[0].values[0].data;
// create a new temporary array
var out = [];
var rows = obj.rows;
// loop over the rows
rows.forEach(function (row) {
var record = row.values[0].data;
// create a new object, loop over the existing array elements
// and add them to the object using the column names as keys
var newRec = {};
for (var i = 0, l = record.length; i < l; i++) {
newRec[translate(colNames[i])] = record[i];
}
// push the new object to the array
out.push(newRec);
});
// return the final object
return { projects: out };
}
DEMO
There is no easy way, and this is really not that complex of an operation, even using for loops. I don't know why you would want to use regex to do this.
I would start with reading out the column values into a numerically indexed array.
So something like:
var sourceData = JSON.parse(yourJSONstring);
var columns = sourceData.columns[0].values[0].data;
Now you have a convenient way to start building your desired object. You can use the columns array created above to provide property key labels in your final object.
var sourceRows = sourceData.rows;
var finalData = {
"projects": []
};
// iterate through rows and write to object
for (i = 0; i < sourceRows.length; i++) {
var sourceRow = sourceRows[i].values.data;
// load data from row in finalData object
for (j = 0; j < sourceRow.length; j++) {
finalData.projects[i][columns[j]] = sourceRow[j];
}
}
That should do the trick for you.

Categories