Covert JSON objects inside json objects into a JSON Array in Javascript - javascript

Hello I have the following JSON structure and I try to make an array of each object inside each object but there is a way to convert it without iterating each element and get every element.
Or maybe using a Javascript function to get object inside objects and convert to an array?
{
"ES": {
"130": {
"code": "A Coruсa",
"name": "A Coruña"
},
"131": {
"code": "Alava",
"name": "Alava"
},
"...": {
"code": "...",
"name": "..."
}
},
"CH": {
"104": {
"code": "AG",
"name": "Aargau"
},
"...": {
"code": "...",
"name": "..."
}
},
"...": {
"...": {
"code": "...",
"name": "..."
}
}
}
This is what I am looking for:
[
{
"code": "A Coruсa",
"name": "A Coruña"
},
{
"code": "Alava",
"name": "Alava"
},
{
"code": "...",
"name": "..."
},
{
"code": "AG",
"name": "Aargau"
},
{
"code": "...",
"name": "..."
},
{
"code": "...",
"name": "..."
}
]
Thanks for your help, I accept any recommendations.

You can use Object.keys(), Array.prototype.reduce() and Array.prototype.map() for iterating over the properties and for assembling the array.
var obj = { "ES": { "130": { "code": "A Coruсa", "name": "A Coruña" }, "131": { "code": "Alava", "name": "Alava" }, }, "CH": { "104": { "code": "AG", "name": "Aargau" } } },
result = Object.keys(obj).reduce(function (r, k) {
return r.concat(Object.keys(obj[k]).map(function (kk) {
return obj[k][kk];
}));
}, []);
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');

I have created a fiddle to convert the data. look at it
https://jsbin.com/suzice/edit?js,output
var data = {
"ES": {
"130": {
"code": "A Coruсa",
"name": "A Coruña"
},
"131": {
"code": "Alava",
"name": "Alava"
},
"...": {
"code": "...",
"name": "..."
}
},
"CH": {
"104": {
"code": "AG",
"name": "Aargau"
},
"...": {
"code": "...",
"name": "..."
}
}
};
var list = [];
Object.keys(data).forEach(function(key){
Object.keys(data[key]).forEach(function(sub_key){
list.push(data[key][sub_key]);
});
console.log(list);
});

Related

Iterate and group the objects using map function

Check for the decimal id and group them accordingly.
Below are the sample and recommended JSON's
Sample JSON
{
"results": [
{
"name": "Download",
"id": "1.1.1"
},
{
"name": "Download",
"id": "1.2"
},
{
"name": "Download",
"id": "1.3.2"
},
{
"name": "Download",
"id": "2"
},
{
"name": "Download",
"id": "2.3"
},
{
"name": "Download",
"id": "3.2"
},
{
"name": "Download",
"id": "3.5"
},
{
"name": "Download",
"id": "4.2"
}
]
}
Would like to iterate and Re-structure the above JSON into below recommended format.
Logic: Should check the id(with and without decimals) and group them based on the number.
For Example:
1, 1.1, 1.2.3, 1.4.5 => data1: [{id: 1},{id: 1.1}....]
2, 2.3, 2.3.4 => data2: [{id: 2},{id: 2.3}....]
3, 3.1 => data3: [{id: 3},{id: 3.1}]
Recommended JSON
{
"results": [
{
"data1": [
{
"name": "Download",
"id": "1.1.1"
},
{
"name": "Download",
"id": "1.2"
},
{
"name": "Download",
"id": "1.3.2"
}
]
},
{
"data2": [
{
"name": "Download",
"id": "2"
},
{
"name": "Download",
"id": "2.3"
}
]
},
{
"data3": [
{
"name": "Download",
"id": "3.2"
},
{
"name": "Download",
"id": "3.5"
}
]
},
{
"data4": [
{
"name": "Download",
"id": "4.2"
}
]
}
]
}
I have tried the below solution but it doesn't group the object
var formatedJSON = [];
results.map(function(d,i) {
formatedJSON.push({
[data+i]: d
})
});
Thanks in advance.
You can use reduce like this. The idea is to create a key-value pair for each data1, data2 etc so that values in this object are the values you need in the final array. Then use Object.values to get those as an array.
const sampleJson = {"results":[{"name":"Download","id":"1.1.1"},{"name":"Download","id":"1.2"},{"name":"Download","id":"1.3.2"},{"name":"Download","id":"2"},{"name":"Download","id":"2.3"},{"name":"Download","id":"3.2"},{"name":"Download","id":"3.5"},{"name":"Download","id":"4.2"}]}
const grouped = sampleJson.results.reduce((a, v) => {
const key = `data${parseInt(v.id)}`;
(a[key] = a[key] || {[key]: []})[key].push(v);
return a;
},{});
console.log({results: Object.values(grouped)})
One liner / Code-golf:
let s={"results":[{"name":"Download","id":"1.1.1"},{"name":"Download","id":"1.2"},{"name":"Download","id":"1.3.2"},{"name":"Download","id":"2"},{"name":"Download","id":"2.3"},{"name":"Download","id":"3.2"},{"name":"Download","id":"3.5"},{"name":"Download","id":"4.2"}]},k;
console.log({results:Object.values(s.results.reduce((a,v)=>(k=`data${parseInt(v.id)}`,(a[k] = a[k]||{[k]:[]})[k].push(v),a),{}))})
Here you go:
var data = {
"results": [
{
"name": "Download",
"id": "1.1.1"
},
{
"name": "Download",
"id": "1.2"
},
{
"name": "Download",
"id": "1.3.2"
},
{
"name": "Download",
"id": "2"
},
{
"name": "Download",
"id": "2.3"
},
{
"name": "Download",
"id": "3.2"
},
{
"name": "Download",
"id": "3.5"
},
{
"name": "Download",
"id": "4.2"
}
]
};
let newSet = new Set();
data.results.forEach(e => {
let key = e.id.substring(0, e.id.indexOf('.'));
console.log(key);
if (newSet.has(key) == false) {
newSet.add(key);
newSet[key] = [];
}
newSet[key].push(e.id);
});
console.log(newSet);
Here's how you'd do it:
var data = {
"results": [
{
"name": "Download",
"id": "1.1.1"
},
{
"name": "Download",
"id": "1.2"
},
{
"name": "Download",
"id": "1.3.2"
},
{
"name": "Download",
"id": "2"
},
{
"name": "Download",
"id": "2.3"
},
{
"name": "Download",
"id": "3.2"
},
{
"name": "Download",
"id": "3.5"
},
{
"name": "Download",
"id": "4.2"
}
]
};
var newData = {
"results": {}
};
data.results.forEach(item => {
var num = item.id.slice(0, 1);
if (newData.results["data" + num]) {
newData.results["data" + num].push(item);
} else {
newData.results["data" + num] = [item];
}
})
data = newData;
console.log(data);
What this does is it iterates through each item in results, gets the number at the front of this item's id, and checks if an array of the name data-{num} exists. If the array exists, it's pushed. If it doesn't exist, it's created with the item.
let input = getInput();
let output = input.reduce((acc, curr)=>{
let {id} = curr;
let majorVersion = 'name' + id.split('.')[0];
if(!acc[majorVersion]) acc[majorVersion]= [];
acc[majorVersion].push(curr);
return acc;
},{})
console.log(output)
function getInput(){
return [
{
"name": "Download",
"id": "1.1.1"
},
{
"name": "Download",
"id": "1.2"
},
{
"name": "Download",
"id": "1.3.2"
},
{
"name": "Download",
"id": "2"
},
{
"name": "Download",
"id": "2.3"
},
{
"name": "Download",
"id": "3.2"
},
{
"name": "Download",
"id": "3.5"
},
{
"name": "Download",
"id": "4.2"
}
]
}
One solution with RegEx for finer control as it would differentiate easily between 1 and 11.
Also this will make sure that even if the same version comes in end(say 1.9 in end) it will put it back in data1.
let newArr2 = ({ results }) =>
results.reduce((acc, item) => {
let key = "data" + /^(\d+)\.?.*/.exec(item.id)[1];
let found = acc.find(i => key in i);
found ? found[key].push(item) : acc.push({ [key]: [item] });
return acc;
}, []);

How to recursively modify nested properties in parsed JSON object

I have parsed JSON object representing response from old OData(v2) service:
"TimesheetDetailsSet": {
"results": [{
"TimesheetNumber": "1",
(...)
"results": [{
"__metadata":
So as you can see its a complex object with nested objects and arrays. I use SAP UI5 framework and I need to modify it, so there will be no intermediary arrays called "results". I want "TimesheetDetailsSet" and other entitysets containg "results" to be independent arrays of objects.
I wrote this method:
var fnConvert = function (oData) {
if (!oData) {
return oData;
}
for (var sKey in oData) {
if (oData.hasOwnProperty(sKey)) {
if (sKey == 'results') {
var oArr = oData[sKey].reduce(function (acc, cur, i) {
acc[i] = cur;
return acc;
}, []);
delete oData[sKey]
for (var i = 0; i < oArr.length; i++) {
oData[i] = oArr[i];
fnConvert(oData[i]);
}
} else if (typeof oData[sKey] === 'object') {
fnConvert(oData[sKey]);
}
}
}
return oData;
};
The only problem is that need entitysets to be arrays not objects.
Result of the method
UPDATE:
I got this:
"TimesheetDetailsSet": {
"results": [{
"__metadata": {
"id": "...",
"uri": "...",
"type": "ZHR_XSS_ASA_ESS_ODATA_SRV.TimesheetDetails"
},
"TimesheetNumber": "1",
"Username": "DEFAULT_USER",
"TimesheetKey": "\/Date(1529280000000)\/",
"TimesheetDetailKey": "00000001-0000-0000-0000-000000000000",
"CostObject": "0001",
"ConstructionSiteSet": {
"results": [{
"__metadata": {
"id": "...",
"uri": "...",
"type": "ZHR_XSS_ASA_ESS_ODATA_SRV.ConstructionSite"
},
"TimesheetKey": "\/Date(1529280000000)\/",
"WorkingOnConstrSiteSince": "18.08.2018",
"Username": "DEFAULT_USER",
"TimesheetDetailKey": "00000001-0000-0000-0000-000000000000",
"ConstructionSiteKey": "00000100-0000-0000-0000-000000000000",
"ConstructionSiteId": "0001",
"ConstructionSiteDetailSet": {
"results": [{
"__metadata": {
"id": "...",
"uri": "...",
"type": "ZHR_XSS_ASA_ESS_ODATA_SRV.ConstructionSiteDetail"
},
And I want to change it into this:
"TimesheetDetailsSet": [{
"__metadata": {
"id": "...",
"uri": "...",
"type": "ZHR_XSS_ASA_ESS_ODATA_SRV.TimesheetDetails"
},
"TimesheetNumber": "1",
"Username": "DEFAULT_USER",
"TimesheetKey": "\/Date(1529280000000)\/",
"TimesheetDetailKey": "00000001-0000-0000-0000-000000000000",
"CostObject": "0001",
"ConstructionSiteSet": [{
"__metadata": {
"id": "...",
"uri": "...",
"type": "ZHR_XSS_ASA_ESS_ODATA_SRV.ConstructionSite"
},
"TimesheetKey": "\/Date(1529280000000)\/",
"WorkingOnConstrSiteSince": "18.08.2018",
"Username": "DEFAULT_USER",
"TimesheetDetailKey": "00000001-0000-0000-0000-000000000000",
"ConstructionSiteKey": "00000100-0000-0000-0000-000000000000",
"ConstructionSiteId": "0001",
"ConstructionSiteDetailSet": [{
"__metadata": {
"id": "...",
"uri": "...",
"type": "ZHR_XSS_ASA_ESS_ODATA_SRV.ConstructionSiteDetail"
},

How to get the corresponding value from two objects

I have first data object which has a list of cafe, and second data object which has a list of cafe types.
I need find, get and display the corresponding type value from first data object and ID value from second data object.
For example: in list of cafe, I have Pinta with "type" : "3", it means that 3 is Bar from second object.
First object:
{
"list": {
"item": [
{
"ID": "31",
"name": "Staut",
"type": "1",
},
{
"ID": "34",
"name": "Pinta",
"type": "3",
}
]
}
}
And second object:
{
"list": {
"item": [
{
"ID": "1",
"name": "Restaurant",
},
{
"ID": "2",
"name": "Cafe",
},
{
"ID": "3",
"name": "Bar",
}
]
}
}
I can do it with Lodash. It is right, but I can't display it and it uses high memory.
getValues: function() {
_.forEach(CafeJSON.list.item, function(cafeValue) {
_.forEach(TypeJSON.list.item, function(typeValue){
if (cafeValue.type == typeValue.ID) {
console.log("Cafe name is: ", cafeValue.name, "and type is: ", typeValue.name)
}
})
})
}
Result:
I'd simplify the types object down to a object having key value pairs in the form of '3': 'Bar', then loop the items once, overriding the type property's value.
let list = {
"list": {
"item": [{
"ID": "31",
"name": "Staut",
"type": "1",
},
{
"ID": "34",
"name": "Pinta",
"type": "3",
}
]
}
}
let types = {
"list": {
"item": [{
"ID": "1",
"name": "Restaurant",
},
{
"ID": "2",
"name": "Cafe",
},
{
"ID": "3",
"name": "Bar",
}
]
}
}
let typesSimplified = types.list.item.reduce((a, b) => {
a[b.ID] = b.name;
return a;
}, {});
list.list.item.forEach(e => {
e.type = typesSimplified[e.type];
});
console.log(list);

Fetch only specific objects from JSON via javascript or jQuery

I would like to fetch only specific objects from the below JSON such as only those JSON objects which have a classDefinition = "com.sap.bpm.wfs.UserTask". Please suggest on how to do this:
var metadata = {
"contents": {
"83eaead8-cfae-459b-9bdd-8b12e32d6715": {
"classDefinition": "com.sap.bpm.wfs.StartEvent",
"id": "startevent1",
"name": "StartEvent1"
},
"13583ac9-596d-4375-b9e1-e5f6f21e829f": {
"classDefinition": "com.sap.bpm.wfs.EndEvent",
"id": "endevent1",
"name": "EndEvent1"
},
"6c2b0935-444b-4299-ac8e-92973ce93558": {
"classDefinition": "com.sap.bpm.wfs.UserTask",
"subject": "Upload document",
"description": "{context.description}",
"priority": "MEDIUM",
"isHiddenInLogForParticipant": false,
"userInterface": "sapui5://html5apps/saptest/com.sap.test",
"recipientUsers": "I311520, I310811",
"id": "usertask1",
"name": "UserTask1"
},
"6728bf81-3d4e-4ae3-a428-1700a2096d34": {
"classDefinition": "com.sap.bpm.wfs.SequenceFlow",
"id": "sequenceflow1",
"name": "SequenceFlow1",
"sourceRef": "83eaead8-cfae-459b-9bdd-8b12e32d6715",
"targetRef": "6c2b0935-444b-4299-ac8e-92973ce93558"
},
"aa99931e-2523-44c3-86b3-d522acdbde10": {
"classDefinition": "com.sap.bpm.wfs.ui.Diagram",
"symbols": {
"760f0725-3400-4d48-b082-5c69ad79d697": {},
"aa9a0d10-63be-4af8-9ac2-4d2b648a18fc": {},
"7fbd11bb-cf82-4a27-97d7-e80dda2014ee": {},
"20c66c48-6058-465e-b500-d69d6e54c028": {},
"2e8f324c-5361-4512-a09a-fc7693f206ba": {}
}
}
}
};
First, metadata.contents property should rather be an array.
If you really cannot change it to an array, then use Object.keys(metadata.contents)
For example:
Object.keys(metadata.contents)
.map(x => metadata.contents[x])
.filter(x => x.classDefinition == 'com.sap.bpm.wfs.UserTask')
var metadata = {
"contents": {
"83eaead8-cfae-459b-9bdd-8b12e32d6715": {
"classDefinition": "com.sap.bpm.wfs.StartEvent",
},
"13583ac9-596d-4375-b9e1-e5f6f21e829f": {
"classDefinition": "com.sap.bpm.wfs.EndEvent",
},
"6c2b0935-444b-4299-ac8e-92973ce93558": {
"classDefinition": "com.sap.bpm.wfs.UserTask",
"subject": "Upload document",
"description": "{context.description}",
"priority": "MEDIUM",
"isHiddenInLogForParticipant": false,
"userInterface": "sapui5://html5apps/saptest/com.sap.test",
"recipientUsers": "I311520, I310811",
"id": "usertask1",
"name": "UserTask1"
},
"6728bf81-3d4e-4ae3-a428-1700a2096d34": {
"classDefinition": "com.sap.bpm.wfs.SequenceFlow",
},
"aa99931e-2523-44c3-86b3-d522acdbde10": {
"classDefinition": "com.sap.bpm.wfs.ui.Diagram",
}
}
}
var filtered = Object.keys(metadata.contents)
.map(x => metadata.contents[x])
.filter(x => x.classDefinition == 'com.sap.bpm.wfs.UserTask')
console.log(filtered)
A simple for loop can be used to get the desired fields:
var temp = [];
for (var index in metadata.contents) {
if (metadata.contents[index].classDefinition == "com.sap.bpm.wfs.UserTask") {
temp.push(metadata.contents[index]);
}
}
Or you can do one by one
var metadata = {
"contents": {
"83eaead8-cfae-459b-9bdd-8b12e32d6715": {
"classDefinition": "com.sap.bpm.wfs.StartEvent",
"id": "startevent1",
"name": "StartEvent1"
},
"13583ac9-596d-4375-b9e1-e5f6f21e829f": {
"classDefinition": "com.sap.bpm.wfs.EndEvent",
"id": "endevent1",
"name": "EndEvent1"
},
"6c2b0935-444b-4299-ac8e-92973ce93558": {
"classDefinition": "com.sap.bpm.wfs.UserTask",
"subject": "Upload document",
"description": "{context.description}",
"priority": "MEDIUM",
"isHiddenInLogForParticipant": false,
"userInterface": "sapui5://html5apps/saptest/com.sap.test",
"recipientUsers": "I311520, I310811",
"id": "usertask1",
"name": "UserTask1"
},
"6728bf81-3d4e-4ae3-a428-1700a2096d34": {
"classDefinition": "com.sap.bpm.wfs.SequenceFlow",
"id": "sequenceflow1",
"name": "SequenceFlow1",
"sourceRef": "83eaead8-cfae-459b-9bdd-8b12e32d6715",
"targetRef": "6c2b0935-444b-4299-ac8e-92973ce93558"
},
"aa99931e-2523-44c3-86b3-d522acdbde10": {
"classDefinition": "com.sap.bpm.wfs.ui.Diagram",
"symbols": {
"760f0725-3400-4d48-b082-5c69ad79d697": {},
"aa9a0d10-63be-4af8-9ac2-4d2b648a18fc": {},
"7fbd11bb-cf82-4a27-97d7-e80dda2014ee": {},
"20c66c48-6058-465e-b500-d69d6e54c028": {},
"2e8f324c-5361-4512-a09a-fc7693f206ba": {}
}
}
}
}
var content = metadata["contents"];
var subContent = content["6c2b0935-444b-4299-ac8e-92973ce93558"];
var classDef = subContent["classDefinition"];
alert(classDef);

How to avoid duplicate records adding inside angular for each loop?

The below directive code is forming an JSON dynamically. I have to form a JSON without dupicate object names.
Angular Code:
bosAppModule.directive('layoutTableCellControlLabelRender',function($compile,$rootScope){
var layoutTableCellControlLabelObj={};
var soJSON = {
entityInfo: {
entity: "",
tenantId: "",
timeStamp: new Date().toJSON().toString()
},
collections: {
}
};
var myobj={};
linkFnTableCellControlLabel=function(scope, element, attributes, controllerCtrl) {
scope.labelData="NO DATA";
angular.forEach(scope.pageObject.collections.objectattribute.rowset, function (value, index) {
if(value.objectattributeid==scope.attributeId){
scope.labelData=value.objectattributelabelname;
scope.attributeName=value.objectattributename;
//$rootScope.$broadcast("NEW_EVENT", scope.attributeName);
angular.forEach(scope.pageObject.collections.object.rowset, function (value2, index2) {
if(value2.tenantobjectid==value.objectattributeobjectid){
scope.objectname=value2.tenantobjectname;
if(!soJSON.collections[scope.objectname]) {
soJSON.collections[scope.objectname]={
"meta": {
"parentreference": "***",
"pkname": "***",
"fkname": "***"
},
"rowset": [],
"rowfilter": []
};
}
}
});
myobj[scope.attributeName]="test";
soJSON.collections[scope.objectname].rowset.push(myobj);
}
});
console.log(JSON.stringify(soJSON));
};
layoutTableCellControlLabelObj.scope={attributeId:'=',layoutData:'=',pageObject:'='};
layoutTableCellControlLabelObj.restrict='AE';
layoutTableCellControlLabelObj.replace='true';
layoutTableCellControlLabelObj.template="<div class='col-xs-12 col-sm-12 col-md-6 col-lg-6' attribute-name={{attributeName}} attribute-id='tablecellcontrol.layouttablecellcontrolbindingobjectattributeid' " +
"layout-data='layoutData' page-object='pageObject'><label class='k-label pull-right'>{{labelData}}</label></div>";
layoutTableCellControlLabelObj.link = linkFnTableCellControlLabel;
return layoutTableCellControlLabelObj;
});
Using aboeve code i am getting the JSON. In this JSON inside rowset records are duplicated because of loop. But i'm bit confused on this. I need avoid it. It should create only one time.
Anyone please help me to achieve this. If you need more details on this. let me know.
JSON
{
"entityInfo": {
"entity": "",
"tenantId": "",
"timeStamp": "2016-04-07T07:25:49.711Z"
},
"collections": {
"Customer29Jan16": {
"meta": {
"parentreference": "***",
"pkname": "***",
"fkname": "***"
},
"rowset": [
{
"CuId": "test",
"Name": "test",
"Quantity": "test",
"Rate": "test",
"Amount": "test"
},
{
"CuId": "test",
"Name": "test",
"Quantity": "test",
"Rate": "test",
"Amount": "test"
},
{
"CuId": "test",
"Name": "test",
"Quantity": "test",
"Rate": "test",
"Amount": "test"
},
{
"CuId": "test",
"Name": "test",
"Quantity": "test",
"Rate": "test",
"Amount": "test"
},
{
"CuId": "test",
"Name": "test",
"Quantity": "test",
"Rate": "test",
"Amount": "test"
}
],
"rowfilter": []
}
}
}
I don't know if it's always the same json but you can probably use uniqby from lodash on your rowset array.
_.uniqBy(json.collections.Customer29Jan16.rowset, function (e) {
return e.CuId;
});
Demo
EDIT
If you have several customers, you can loop over a customer array :
arrayOfCustomers = (Object.keys(json.collections));
for(var i = 0 ; i < arrayOfCustomers.length; i++){
json.collections[arrayOfCustomers[i]].rowset = _.uniqBy(json.collections[arrayOfCustomers[i]].rowset, function (e) {
return e.CuId;
});
}
https://jsfiddle.net/kq9gtdr0/23/

Categories