Restructure JSON object - javascript

I have the following array:
var res = {
"status": "Success",
"data": [
{"assignedTo":"0", "createdDate":"23-07-2013", "count":"2"},
{"assignedTo":"182398", "createdDate":"01-08-2013", "count":"2"},
{"assignedTo":"182398", "createdDate":"23-07-2013", "count":"2"},
{"assignedTo":"182398", "createdDate":"24-07-2013", "count":"12"},
{"assignedTo":"182398", "createdDate":"22-07-2013", "count":"1"},
{"assignedTo":"182398", "createdDate":"30-07-2013", "count":"4"},
{"assignedTo":"182398", "createdDate":"31-07-2013", "count":"19"},
{"assignedTo":"185271", "createdDate":"24-07-2013", "count":"2"},
{"assignedTo":"185271", "createdDate":"23-07-2013", "count":"1"}
]
}
Now I want to make one json array from the above with the value of data to another json
which will be like:
[
{
key: "0",
values: [["23-07-2013", 2]]
},
{
key: "182398",
values: [["01-08-2013", 2],
["23-07-2013", 2],
["24-07-2013", 12],
["22-07-2013", 1],
["30-7-2013", 4],
["31-7-2013", 19]
},
{
key: "185271",
values: [["24-07-2013", 2],
["23-07-2013", 1]
}
]
I have tried like the following:
for (i in res.data) {
for (k in res.data[i]) {
time_val += "[" + res.data[i]['createdDate'] + ","
+ res.data[i]['count'] + "],";
cumulative_val += '{key:"' + res.data[i]['assignedTo']
+ '",values:'+time_val+'},';
}
}
Could you please guide me how to do this?
Thanks in advance.

Something like this in javascript:
var res = {"status":"Success","data":[{"assignedTo":"0","createdDate":"23-07-2013","count":"2"},
{"assignedTo":"182398","createdDate":"01-08-2013","count":"2"},
{"assignedTo":"182398","createdDate":"23-07-2013","count":"2"},
{"assignedTo":"182398","createdDate":"24-07-2013","count":"12"},
{"assignedTo":"182398","createdDate":"22-07-2013","count":"1"},
{"assignedTo":"182398","createdDate":"30-07-2013","count":"4"},
{"assignedTo":"182398","createdDate":"31-07-2013","count":"19"},
{"assignedTo":"185271","createdDate":"24-07-2013","count":"2"},
{"assignedTo":"185271","createdDate":"23-07-2013","count":"1"}]
}
//Wanted mixed object
var temp = [];
//Store keys, so we do not need to check from temp if key allready exists
var temp_keys = {};
//Loop trough data
for (var i in res.data)
{
//Check if key is allready stored in object
if (!temp_keys[res.data[i]['assignedTo']])
{
//Store new key, and save it''s position
temp_keys[res.data[i]['assignedTo']] = temp.length;
//Create new array element as new object
temp.push(
{
'key' : res.data[i]['assignedTo'],
'values': []
}
);
}
//Save values into correct position
temp[temp_keys[res.data[i]['assignedTo']]]['values'].push([res.data[i]['createdDate'], res.data[i]['count']]);
}
console.log(temp);
console.log(JSON.stringify(temp));
JSON Example Output:
[{"key":"0","values":[["23-07-2013","2"]]},{"key":"182398","values":[["01-08-2013","2"],["23-07-2013","2"],["24-07-2013","12"],["22-07-2013","1"],["30-07-2013","4"],["31-07-2013","19"]]},{"key":"185271","values":[["24-07-2013","2"],["23-07-2013","1"]]}]

use these functions
json_decode
get_object_vars

I guess that the cumulative_key is in the wrong loop:
lastKey = res.data[0]['assignedTo'];
for(i in res.data) {
if(res.data[i]['assignedTo'] != last) {
cumulative_val += '{key:"'+res.data[i]['assignedTo']+'",values:'+time_val+'},';
}
time_val += "["+res.data[i]['createdDate']+","+res.data[i]['count']+"],";
}
You should think about manipulate real array object and then after make a json encoding.

Try this code...
var _root = new Array();
for (i in res.data) {
for (k in res.data[i]) {
var _child = [res.data[i]['createdDate'], res.data[i]['count']];
var _parent = [{"key":res.data[i]['assignedTo'], "values": _child}];
}
_root.push(_parent);
}
var _JSON_ = JSON.stringify(_root);

A slightly different solution just for the sake of variety
let res = {
"status": "Success", "data": [
{"assignedTo": "185271", "createdDate": "23-07-2013", "count": "1"},
{"assignedTo": "182398", "createdDate": "01-08-2013", "count": "2"},
{"assignedTo": "182398", "createdDate": "23-07-2013", "count": "2"},
{"assignedTo": "182398", "createdDate": "24-07-2013", "count": "12"},
{"assignedTo": "185271", "createdDate": "24-07-2013", "count": "2"},
{"assignedTo": "182398", "createdDate": "22-07-2013", "count": "1"},
{"assignedTo": "0", "createdDate": "23-07-2013", "count": "2"},
{"assignedTo": "182398", "createdDate": "30-07-2013", "count": "4"},
{"assignedTo": "182398", "createdDate": "31-07-2013", "count": "19"},
]
};
let values = [];
let ctrl = '';
let interim = {};
for (const obj of res.data) {
const id = obj.assignedTo;
values = interim[obj.assignedTo] ? interim[obj.assignedTo].values : [];
values.push([obj.createdDate, obj.count])
interim[obj.assignedTo] = {"key": obj.assignedTo, "values": values};
ctrl = ctrl !== id ? id : ctrl;
}
let reshaped = Object.values(interim);
console.log(JSON.stringify(reshaped, null, 0));
and the result is
[{"key": "0", "values": [["23-07-2013", "2"]]},
{"key": "182398", "values": [["01-08-2013", "2"],
["23-07-2013", "2"],
["24-07-2013", "12"],
["22-07-2013", "1"],
["30-07-2013", "4"],
["31-07-2013", "19"]]},
{"key": "185271", "values": [["23-07-2013", "1"],
["24-07-2013", "2"]]}
]
I "shuffled" the input data a bit just to avoid a mistake of assuming the data is always sorted... which I almost fell into twice while was writing up this snippet.

Related

Sort-Index from nested JSON with Javascript

How can I recursively add a sort key to an infinite hierarchy like this:
[
{
"id": "D41F4D3D-EA9C-4A38-A504-4415086EFFF8",
"name": "A",
"parent_id": null,
"sortNr": 1,
"children": [
{
"id": "07E556EE-F66F-49B5-B5E4-54AFC6A4DD9F",
"name": "A-C",
"parent_id": "D41F4D3D-EA9C-4A38-A504-4415086EFFF8",
"sortNr": 3,
"children": []
},
{
"id": "8C63981E-0D30-4244-94BE-658BAAF40EF3",
"name": "A-A",
"parent_id": "D41F4D3D-EA9C-4A38-A504-4415086EFFF8",
"sortNr": 1,
"children": [
{
"id": "0BA32F23-A2CD-4488-8868-40AD5E0D3F09",
"name": "A-A-A",
"parent_id": "8C63981E-0D30-4244-94BE-658BAAF40EF3",
"sortNr": 1,
"children": []
}
]
},
{
"id": "17A07D6E-462F-4983-B308-7D0F6ADC5328",
"name": "A-B",
"parent_id": "D41F4D3D-EA9C-4A38-A504-4415086EFFF8",
"sortNr": 2,
"children": []
}
]
},
{
"id": "64535599-13F1-474C-98D0-67337562A621",
"name": "B",
"parent_id": null,
"sortNr": 2,
"children": []
},
{
"id": "1CE38295-B933-4457-BBAB-F1B4A4AFC828",
"name": "C",
"parent_id": null,
"sortNr": 3,
"children": [
{
"id": "D1E02274-33AA-476E-BA31-A4E60438C23F",
"name": "C-A",
"parent_id": "1CE38295-B933-4457-BBAB-F1B4A4AFC828",
"sortNr": 1,
"children": [
{
"id": "76A8259C-650D-482B-91CE-D69D379EB759",
"name": "C-A-A",
"parent_id": "D1E02274-33AA-476E-BA31-A4E60438C23F",
"sortNr": 1,
"children": []
}
]
}
]
}
]
I want to get a sortable index.
For example 0000.0001.0003 or 0001.0003 for node A-C.
The function for leadingZeroes is
function fillZeroes (num) {
var result = ('0000'+num).slice(-4);
if (num===null){
return result
} else {
return '0000';
}
}
It should be sorted by sort number in each level of hierarchy, the sort number should be set newly every time, because I want to do rearrangement by setting it 1,5 to insert it between 1 and 2 (later for drag and drop capability). so 1;1,5;2 should become 1;2;3 and can then be translated to a sort-index like above.
I will also need it for indentation and breadcrumb-stuff.
How do I insert the proper sort-index to each object ?
The question is mainly about the recursion part. I am quite new to JavaScript
Thanks a lot
Based on great answer by #georg. A bit adjusted solution based on sortNr object property.
You can run it straight as is with json being your object. The sort index is written into sortOrder property.
// Mutates the given object in-place.
// Assigns sortOrder property to each nested object
const indexJson = (json) => {
const obj = {children: json};
const format = (xs) => xs.map(x => pad(x, 4)).join('.');
const pad = (x, w) => (10 ** w + x).toString().slice(-w);
const renumber = (obj, path) => {
obj.path = path;
obj.sortOrder = format(path);
obj.children.slice()
.sort((obj1, obj2) => obj1.sortNr - obj2.sortNr)
.forEach((c, n) => renumber(c, path.concat(n+1)));
};
renumber(obj, []);
};
indexJson(json);
console.log(JSON.stringify(json, null, 2));
Basically
let renumber = (obj, path) => {
obj.path = path
obj.children.forEach((c, n) => renumber(c, path.concat(n)))
}
renumber({children: yourData}, [])
this creates a path property, which is an array of relative numbers. If you want to format it in a special way, then you can do
obj.path = format(path)
where format is like
let format = xs => xs.map(pad(4)).join(',')
let pad = w => x => (10 ** w + x).toString().slice(-w)

Create an array of objects from another array of objects

I have an object as follows:
{
"id": 1,
"dataLockVersion": 0,
"auditData": {
"createDate": "2018-09-18T11:41:28.362",
"createUser": "XXX",
"updateDate": null,
"updateUser": null
},
"property1": 14021,
"property2": {...},
"property3": "Obj"
}
And I have an array that contains multiple objects in that format.
I want to create a new array of objects from this array, which will contain objects in this format :
{
"property1": 14021,
"property2": {...},
"property3": "Obj"
}
This is what I tried :
var result = [];
for (i = 0; i < arr.length; i++) {
delete arr[i].auditData;
delete arr[i].dataLockVersion;
delete arr[i].domainObjectDescription;
delete arr[i].id;
result.push(arr[i]);
}
Is there a better way to do this ?
use map and object destructure
const result = array
.map(
({ property1, property2, property3 })
=> ({ property1, property2, property3 }));
You can simply use Array.map() and object destructuring for this:
let arr =[{ "id": 1, "dataLockVersion": 0, "auditData": { "createDate": "2018-09-18T11:41:28.362", "createUser": "XXX", "updateDate": null, "updateUser": null }, "property1": 14021, "property2": {"x" :1}, "property3": "Obj" }, { "id": 1, "dataLockVersion": 0, "auditData": { "createDate": "2018-09-18T11:41:28.362", "createUser": "XXX", "updateDate": null, "updateUser": null }, "property1": 14021, "property2": {"x" :12}, "property3": "Obj" }];
let result = arr.map(({property1,property2,property3})=>Object.assign({},{property1,property2,property3}));
console.log(result);
I'd use lodash.pick as a oneliner clean and efficient solution.
Pretty often it turns out that this kind of logic will be needed in other parts of the app.
In your case it would be:
var newArrayWithPickedProperties = array.map(item => {
return _.pick(item, ['property1', 'property2', 'property3']);
})
If you go this way ensure you import only lodash.pick not entire lodash library.
you can try this:
var data = [
{"id": 1,"dataLockVersion": 0,"auditData": {"createDate": "2018-09-18T11:41:28.362","createUser": "XXX","updateDate": null,"updateUser": null},"property1": 14021,"property2": {},"property3": "Obj"},
{"id": 2,"dataLockVersion": 1,"auditData": {"createDate": "2018-09-18T11:41:28.362","createUser": "YYY","updateDate": null,"updateUser": null},"property1": 140221,"property2": {},"property3": "Obj3"}
];
var res = data.map(function(m){return {property1: m.property1, property2: m.property2, property3: m.property3};})
console.log(res);
Or if you like tricks and all values are string or number or object that contains them, you can use this (in very heavy objects is not recommended):
let data = [
{"id": 1,"dataLockVersion": 0,"auditData": {"createDate": "2018-09-18T11:41:28.362","createUser": "XXX","updateDate": null,"updateUser": null},"property1": 14021,"property2": {},"property3": "Obj"},
{"id": 2,"dataLockVersion": 1,"auditData": {"createDate": "2018-09-18T11:41:28.362","createUser": "YYY","updateDate": null,"updateUser": null},"property1": 140221,"property2": {},"property3": "Obj3"}
];
var res=[];
JSON.stringify(data).replace(/"(property1)"\:(.+?),.+?"(property\d+)"\:(.+?)(?=})/gi, function(a){res.push(JSON.parse("{"+a+"}"));});
console.log(res);
If you have n number of property with fixed 1st 3 keys, you can do destructuring assignment.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
let data = [
{"id": 1,"dataLockVersion": 0,"auditData": {"createDate": "2018-09-18T11:41:28.362","createUser": "XXX","updateDate": null,"updateUser": null},"property1": 14021,"property2": {},"property3": "Obj","property4":"yo","property5":"hey"},
{"id": 2,"dataLockVersion": 1,"auditData": {"createDate": "2018-09-18T11:41:28.362","createUser": "YYY","updateDate": null,"updateUser": null},"property1": 140221,"property2": {},"property3": "Obj3"}
];
const arr=data.map(a=>{
let {id,dataLockVersion,auditData,...props}=a
return props;
}
)
console.log(arr);
If data is from a JSON string, the JSON.parse reviver parameter can be used to exclude properties :
var json = '{"id":1,"dataLockVersion":0,"auditData":{"createDate":"2018-09-18T11:41:28.362","createUser":"XXX","updateDate":null,"updateUser":null},"property1":14021,"property2":"{...}","property3":"Obj"}'
var obj = JSON.parse(json, (key, value) => /id|data/i.test(key) ? void 0 : value)
console.log( obj )

Evaluating key values in multi-dimensional object

I have a multi-dimensional object that looks like this:
{
"links": [{"source":"58","target":"john","total":"95"},
{"source":"60","target":"mark","total":"80"}],
"nodes":
[{"name":"john"}, {"name":"mark"}, {"name":"rose"}]
}
I am trying to evaluate the value of "total" in "links." I can do this in a one-dimensional array, like this:
for (var i = 0; i < data.length; i++) {
for (var key in data[i]) {
if (!isNaN(data[i][key])) {
data[i][key] = +data[i][key];
}
}
};
But I have not been able to figure out how to do this in two-dimensions (especially calling the value of key "total" by name).
Can anybody set me on the right track? Thank you!
Starting from the principle that the structure of your array is this, you can to iterate the keys and the values:
var obj = {
"links": [{"source":"58","target":"john","total":"95"},
{"source":"60","target":"mark","total":"80"}],
"nodes":
[{"name":"john"}, {"name":"mark"}, {"name":"rose"}]
};
for (var key in obj){
obj[key].forEach(function(item){
for(var subkey in item){
if (subkey == 'total')
console.log(item[subkey]);
};
});
};
You can get total using reduce
check this snippet
var obj = {
"links": [{
"source": "58",
"target": "john",
"total": "95"
}, {
"source": "60",
"target": "mark",
"total": "80"
}, {
"source": "60",
"target": "mark",
"total": "80"
}],
"nodes": [{
"name": "john"
}, {
"name": "mark"
}, {
"name": "rose"
}]
}
var links = obj.links;
var sum = links.map(el => el.total).reduce(function(prev, curr) {
return parseInt(prev, 10) + parseInt(curr, 10);
});
console.log(sum);
Hope it helps
Extract the values from the array, convert them to numbers and add them up.
Array.prototype.map() and Array.prototype.reduce() are pretty helpful here:
var data = {"links":[{"source":"58","target":"john","total":"95"},{"source":"60","target":"mark","total":"80"}], "nodes":[{"name":"john"}, {"name":"mark"}, {"name":"rose"}]};
var sum = data.links.map(function(link) {
return +link.total;
}).reduce(function(a, b) {
return a + b;
});
console.log(sum);

Access nested members in JSON

I'm trying to access members in a json, however I am running into some trouble. Here is an example of one of the json objects, stored in var obj:
var fs = require('fs');
var obj = [
{
"_id": "52d7f816f96d7f6f31fbb680",
"regNum": "0361300035313000002",
"sd": "2013-01-01T00:00:00",
"pd": "2013-01-25T09:30:29Z",
"prd": "2012-12-18",
"p": 1395000000,
"pt": [
{
"name": name here",
"price": 1395000000,
"OKDP": {
"code": "5520109",
"name": "name here"
},
"sid": "25484812",
"sum": "1395000000",
"OKEI": {
"code": "796",
"name": "name two"
},
"quantity": "1"
}
],
"b": 0,
"c": 0,
"s": 0
}
];
I'm trying to access the sid and sum values, by doing the following:
var sid = [];
var sum = [];
obj.forEach(block => {
var sidOut = block.pt.sid;
var sumOut = block.pt.sum;
sid.push(sidOut);
sum.push(sumOut);
});
console.log(sid);
console.log(sum);
I tried the solution here, however, when I run these it gives me [ undefined ] errors.
Why am I unable to access this two values?
if you see your pt is an array of an object [{}] so you need to select which element you want to access so
var sidOut = block.pt[0].sid;
var sumOut = block.pt[0].sum;
should get you the right result

In JSON Object parent key name remove and Include its inner content

This is my JSON Object in this i want to remove "item" key from json and want to keep its inner object include with "children" and its tree like JOSN. How can I do this?
[
{
"item": {
"id": 11865,
"parentid": null,
"levelid": 63,
"name": "Total"
},
"children": [
{
"item": {
"id": 10143,
"parentid": 11865,
"levelid": 19,
"name": "Productive"
}
}
]
}
]
If I'm understanding what you want your object to look like after correctly, then this should do the trick:
var arrayOfObjects = [
{
"item": {
"id": 11865,
"parentid": null,
"levelid": 63,
"name": "Total"
},
"children": [
{
"item": {
"id": 10143,
"parentid": 11865,
"levelid": 19,
"name": "Productive"
}
}
]
}
]
arrayOfObjects.forEach(function(obj) {
obj.id = obj.item.id;
obj.parentid = obj.item.parentid;
obj.levelid = obj.item.levelid;
obj.name = obj.item.name;
delete obj.item;
});
All this is doing is manually moving the data from obj.item to obj and then deleting obj.item entirely.
I would do this:
//your original array of objects
var array = [{
"item": {
"id": 11865,
"parentid": null,
"levelid": 63,
"name": "Total"
},
"children": [
{
"item": {
"id": 10143,
"parentid": 11865,
"levelid": 19,
"name": "Productive"
}
}
]
}, ...];
array.forEach(function(parent) {
flattenKey(parent, 'item');
});
function flattenKey(parent, keyName) {
var section = parent[keyName];
var child = section ? section : {};
var keys = Object.keys(child);
keys.forEach(function(key) {
parent[key] = child[key];
})
delete parent[keyName];
}
basically, the function flattenKey would flatten any key for a given object (given its key).
logic is similar to other solutions here: iterate through child keys and assign their values to the parent object (flattening).
then it deletes the child key after step 1.
try
objArray = objArray.map( function(value){
var item = value.item;
for( var key in item )
{
value[key] = item[key];
}
delete value.item;
return value;
});
DEMO
Explanation
1) Use map to iterate on each item (value) of this given array objArray.
2) Get the item property of value, assign them to value directly
3) Finally delete the item property of the value.
Faster option
objArray = objArray.map( function(value){
var item = value.item;
var itemKeys = Object.keys(item);
for( var counter = 0; counter < itemKeys.length; counter++ )
{
value[itemKeys[counter]] = item[itemKeys[counter]];
}
delete value.item;
return value;
});
You can use a recursion, which keeps the content of item and adds the children property as well.
function delItem(a, i, aa) {
var children = a.children;
if (a.item) {
aa[i] = a.item;
aa[i].children = children;
delete a.item;
}
Array.isArray(children) && children.forEach(delItem);
}
var array = [{ "item": { "id": 11865, "parentid": null, "levelid": 63, "name": "Total" }, "children": [{ "item": { "id": 10143, "parentid": 11865, "levelid": 19, "name": "Productive" } }] }];
array.forEach(delItem);
document.write('<pre>' + JSON.stringify(array, 0, 4) + '</pre>');

Categories

Resources