How to have a JSON data through a "complex architecture" - javascript

I work with an API that returns a rather particular JSON file ...
It's been 2 days that I try to do something but I can not do it, that's why I leave it to you :)
First of all my JSON file looks like:
[
{
"_id": 14080,
"name": "Amulette Séculaire",
"lvl": "200",
"type": "Amulette",
"imgUrl": "https://s.ankama.com/www/static.ankama.com/dofus/www/game/items/200/1230.png",
"url": "https://www.dofus.com/fr/mmorpg/encyclopedie/equipements/14080-amulette-seculaire",
"description": "Finalement, le secteur de la bijouterie n'a pas tellement évolué ces cent dernières années.",
"stats": [
{
"Vitalité": {
"from": "251",
"to": "300"
}
},
{
"Intelligence": {
"from": "61",
"to": "80"
}
},
{
"Agilité": {
"from": "16",
"to": "25"
}
},
{
"Sagesse": {
"from": "31",
"to": "40"
}
},
{
"PA": {
"from": "1"
}
},
{
"Prospection": {
"from": "16",
"to": "20"
}
},
{
"Dommages Feu": {
"from": "8",
"to": "12"
}
},
{
"Dommages Air": {
"from": "8",
"to": "12"
}
},
{
"% Résistance Neutre": {
"from": "6",
"to": "8"
}
},
{
"% Résistance Feu": {
"from": "6",
"to": "8"
}
},
{
"Résistance Critiques": {
"from": "11",
"to": "15"
}
}
],
"condition": [],
"recipe": [
{
"Galet brasillant": {
"id": "12740",
"url": "https://www.dofus-touch.com/fr/mmorpg/encyclopedie/ressources/12740-galet-brasillant",
"imgUrl": "https://s.ankama.com/www/static.ankama.com/dofus/www/game/items/52/15289.w48h48.png",
"type": "Galet",
"lvl": "150",
"quantity": "3"
}
},
{
"Poudre glaciale": {
"id": "13154",
"url": "https://www.dofus-touch.com/fr/mmorpg/encyclopedie/ressources/13154-poudre-glaciale",
"imgUrl": "https://s.ankama.com/www/static.ankama.com/dofus/www/game/items/52/48292.w48h48.png",
"type": "Poudre",
"lvl": "190",
"quantity": "7"
}
},
{
"Poil d'aisselle de Missiz Frizz": {
"id": "13935",
"url": "https://www.dofus-touch.com/fr/mmorpg/encyclopedie/ressources/13935-poil-aisselle-missiz-frizz",
"imgUrl": "https://s.ankama.com/www/static.ankama.com/dofus/www/game/items/52/54691.w48h48.png",
"type": "Poil",
"lvl": "200",
"quantity": "9"
}
},
{
"Pédoncule de Mérulor": {
"id": "13978",
"url": "https://www.dofus-touch.com/fr/mmorpg/encyclopedie/ressources/13978-pedoncule-merulor",
"imgUrl": "https://s.ankama.com/www/static.ankama.com/dofus/www/game/items/52/119008.w48h48.png",
"type": "Champignon",
"lvl": "200",
"quantity": "6"
}
},
{
"Œil de Cycloïde": {
"id": "13988",
"url": "https://www.dofus-touch.com/fr/mmorpg/encyclopedie/ressources/13988-oeil-cycloide",
"imgUrl": "https://s.ankama.com/www/static.ankama.com/dofus/www/game/items/52/109603.w48h48.png",
"type": "Œil",
"lvl": "200",
"quantity": "30"
}
},
{
"Queue de Sinistrofu": {
"id": "13991",
"url": "https://www.dofus-touch.com/fr/mmorpg/encyclopedie/ressources/13991-queue-sinistrofu",
"imgUrl": "https://s.ankama.com/www/static.ankama.com/dofus/www/game/items/52/65764.w48h48.png",
"type": "Queue",
"lvl": "200",
"quantity": "3"
}
},
{
"Bandelette du Comte Harebourg": {
"id": "13995",
"url": "https://www.dofus-touch.com/fr/mmorpg/encyclopedie/ressources/13995-bandelette-comte-harebourg",
"imgUrl": "https://s.ankama.com/www/static.ankama.com/dofus/www/game/items/52/15831.w48h48.png",
"type": "Ressources diverses",
"lvl": "200",
"quantity": "1"
}
},
{
"Œil de verre": {
"id": "14145",
"url": "https://www.dofus-touch.com/fr/mmorpg/encyclopedie/ressources/14145-oeil-verre",
"imgUrl": "https://s.ankama.com/www/static.ankama.com/dofus/www/game/items/52/109604.w48h48.png",
"type": "Œil",
"lvl": "200",
"quantity": "1"
}
}
],
"setId": 271
}
]
For the moment i extract data like that:
for (var i = 0; i < pets.length; i++) {
petsTable = {
name: pets[i].name,
level: pets[i].lvl,
type: pets[i].type,
description: pets[i].description,
imgUrl: pets[i].imgUrl,
url: pets[i].url,
condition: pets[i].condition,
recipe: pets[i].recipe
};
and to go on recipe i use an array :
var petsRecipe = [];
for (var x = 0; x < petsTable.recipe.length; x++) {
petsRecipe.push(petsTable.recipe[x]);
}
This array result :
Array(8) [Object, Object, Object, Object, Object, Object, Object, Object]
And an example of the first Object is :
0:
Galet brasillant:
id: "12740"
imgUrl: "https://s.ankama.com/www/static.ankama.com/dofus/www/game/items/52/15289.w48h48.png"
lvl: "150"
quantity: "3"
type: "Galet"
url: "https://www.dofus-touch.com/fr/mmorpg/encyclopedie/ressources/...
But I can not collect the id or the "lvl", have you ideas ?
Thanks for your help

The problem with the recipe array is that every object it contains has a structure like this :
{
"Poudre glaciale": {
"id": "13154",
"lvl": "190",
"quantity": "7"
}
}
In other words, each object has one key (with a different name each time), and the object you want to reach is nested under this variable key, which makes it tricky to reach.
You can access the key name ("poudre glaciale") using Object.keys(obj)[0]. Then you can reach the sub-object easily :
const recipe = [{
"Galet brasillant": {
"id": "12740",
"url": "https://www.dofus-touch.com/fr/mmorpg/encyclopedie/ressources/12740-galet-brasillant",
"imgUrl": "https://s.ankama.com/www/static.ankama.com/dofus/www/game/items/52/15289.w48h48.png",
"type": "Galet",
"lvl": "150",
"quantity": "3"
}
},
{
"Poudre glaciale": {
"id": "13154",
"url": "https://www.dofus-touch.com/fr/mmorpg/encyclopedie/ressources/13154-poudre-glaciale",
"imgUrl": "https://s.ankama.com/www/static.ankama.com/dofus/www/game/items/52/48292.w48h48.png",
"type": "Poudre",
"lvl": "190",
"quantity": "7"
}
},
{
"Poil d'aisselle de Missiz Frizz": {
"id": "13935",
"url": "https://www.dofus-touch.com/fr/mmorpg/encyclopedie/ressources/13935-poil-aisselle-missiz-frizz",
"imgUrl": "https://s.ankama.com/www/static.ankama.com/dofus/www/game/items/52/54691.w48h48.png",
"type": "Poil",
"lvl": "200",
"quantity": "9"
}
},
{
"Pédoncule de Mérulor": {
"id": "13978",
"url": "https://www.dofus-touch.com/fr/mmorpg/encyclopedie/ressources/13978-pedoncule-merulor",
"imgUrl": "https://s.ankama.com/www/static.ankama.com/dofus/www/game/items/52/119008.w48h48.png",
"type": "Champignon",
"lvl": "200",
"quantity": "6"
}
},
{
"Œil de Cycloïde": {
"id": "13988",
"url": "https://www.dofus-touch.com/fr/mmorpg/encyclopedie/ressources/13988-oeil-cycloide",
"imgUrl": "https://s.ankama.com/www/static.ankama.com/dofus/www/game/items/52/109603.w48h48.png",
"type": "Œil",
"lvl": "200",
"quantity": "30"
}
},
{
"Queue de Sinistrofu": {
"id": "13991",
"url": "https://www.dofus-touch.com/fr/mmorpg/encyclopedie/ressources/13991-queue-sinistrofu",
"imgUrl": "https://s.ankama.com/www/static.ankama.com/dofus/www/game/items/52/65764.w48h48.png",
"type": "Queue",
"lvl": "200",
"quantity": "3"
}
},
{
"Bandelette du Comte Harebourg": {
"id": "13995",
"url": "https://www.dofus-touch.com/fr/mmorpg/encyclopedie/ressources/13995-bandelette-comte-harebourg",
"imgUrl": "https://s.ankama.com/www/static.ankama.com/dofus/www/game/items/52/15831.w48h48.png",
"type": "Ressources diverses",
"lvl": "200",
"quantity": "1"
}
},
{
"Œil de verre": {
"id": "14145",
"url": "https://www.dofus-touch.com/fr/mmorpg/encyclopedie/ressources/14145-oeil-verre",
"imgUrl": "https://s.ankama.com/www/static.ankama.com/dofus/www/game/items/52/109604.w48h48.png",
"type": "Œil",
"lvl": "200",
"quantity": "1"
}
}
]
const output = recipe.map( obj => {
let keyName = Object.keys(obj)[0]; // "Galet brasillant", "poudre glaciale", etc.
return obj[keyName]; // the object containing attributes
})
console.log(output[0])
Edit :
If you want the id of "Poudre glaciale", you have to do this :
First, filter the recipe array to keep only the object you want : recipe.filter( obj => Object.keys(obj)[0] === "Poudre glaciale")
Then, extract the first (and only) object from this filtered array with [0]
Then enter inside the "Poudre glaciale" key with ["Poudre glaciale"]
And then you can access the id
So the full solution :
const id = recipe.filter( obj => Object.keys(obj)[0] === "Poudre glaciale")[0]["Poudre glaciale"].id

Related

More efficient way to remove from an object attributes present in a group of objects

I'm manipulating some javascript objects and I want to know if is there a more efficient and easy way to process my data.
I already do that, but I'm a beginner in js.
I have four objects with this structure: basically there is an array of blocks and any object has a different number of blocks. In every block, in the features attribute, I have another array with some features.
Then I have another object, and I have to remove from this object (I call it structure) blocks and features that are not present in my four initial object.
This is a sample product object
[
{
"ID": 16293,
"SortNo": "20",
"FeatureGroup": {
"ID": "148",
"Name": {
"Value": "Design",
"Language": "IT"
}
},
"Features": [
{
"Localized": 0,
"ID": "155744521",
"Type": "dropdown",
"Value": "Round",
"CategoryFeatureId": "85327",
"CategoryFeatureGroupID": "16293",
"SortNo": "155",
"PresentationValue": "Rotondo",
"RawValue": "Round",
"LocalValue": [],
"Description": "The external form",
"Mandatory": "1",
"Searchable": "0",
"Feature": {
"ID": "9397",
"Sign": "",
"Measure": {
"ID": "29",
"Sign": "",
"Signs": {
"ID": "",
"_": "",
"Language": "IT"
}
},
"Name": {
"Value": "Forma",
"Language": "IT"
}
}
},
{
"Localized": 0,
"ID": "155655523",
"Type": "multi_dropdown",
"Value": "White",
"CategoryFeatureId": "85298",
"CategoryFeatureGroupID": "16293",
"SortNo": "90",
"PresentationValue": "Bianco",
"RawValue": "White",
"LocalValue": [],
"Description": "The colour of the housing",
"Mandatory": "1",
"Searchable": "1",
"Feature": {
"ID": "10059",
"Sign": "",
"Measure": {
"ID": "29",
"Sign": "",
"Signs": {
"ID": "",
"_": "",
"Language": "IT"
}
},
"Name": {
"Value": "Colore struttura",
"Language": "IT"
}
}
},
{
"Localized": 0,
"ID": "155655525",
"Type": "multi_dropdown",
"Value": "White",
"CategoryFeatureId": "85301",
"CategoryFeatureGroupID": "16293",
"SortNo": "80",
"PresentationValue": "Bianco",
"RawValue": "White",
"LocalValue": [],
"Description": "The colour of the band",
"Mandatory": "1",
"Searchable": "1",
"Feature": {
"ID": "11025",
"Sign": "",
"Measure": {
"ID": "29",
"Sign": "",
"Signs": {
"ID": "",
"_": "",
"Language": "IT"
}
},
"Name": {
"Value": "Colore cinturino",
"Language": "IT"
}
}
},
{
"Localized": 0,
"ID": "219617494",
"Type": "y_n",
"Value": "Y",
"CategoryFeatureId": "168947",
"CategoryFeatureGroupID": "16293",
"SortNo": "-6",
"PresentationValue": "Sì",
"RawValue": "Y",
"LocalValue": [],
"Description": "The product is protected from water",
"Mandatory": "0",
"Searchable": "0",
"Feature": {
"ID": "7509",
"Sign": "",
"Measure": {
"ID": "26",
"Sign": "",
"Signs": {
"ID": "",
"_": "",
"Language": "IT"
}
},
"Name": {
"Value": "Resistente all'acqua",
"Language": "IT"
}
}
}
]
},
{
"ID": 34567,
"SortNo": "20",
"FeatureGroup": {
"ID": "184",
"Name": {
"Value": "Prestazione",
"Language": "IT"
}
},
"Features": [
{
"Localized": 0,
"ID": "155744528",
"Type": "y_n",
"Value": "N",
"CategoryFeatureId": "94697",
"CategoryFeatureGroupID": "34567",
"SortNo": "800",
"PresentationValue": "No",
"RawValue": "N",
"LocalValue": [],
"Description": "La Frequenza modulare radio produce la miglior recezione di qualsiasi canale radio. Quando viene usato un auricolare, produce un effetto di suono da stereo r",
"Mandatory": "1",
"Searchable": "0",
"Feature": {
"ID": "2172",
"Sign": "",
"Measure": {
"ID": "26",
"Sign": "",
"Signs": {
"ID": "",
"_": "",
"Language": "IT"
}
},
"Name": {
"Value": "Radio FM",
"Language": "IT"
}
}
},
{
"Localized": 0,
"ID": "155744530",
"Type": "multi_dropdown",
"Value": "Not supported",
"CategoryFeatureId": "85357",
"CategoryFeatureGroupID": "34567",
"SortNo": "500",
"PresentationValue": "Non supportato",
"RawValue": "Not supported",
"LocalValue": [],
"Description": "Types of memory cards which can be used with this product.",
"Mandatory": "1",
"Searchable": "0",
"Feature": {
"ID": "730",
"Sign": "",
"Measure": {
"ID": "29",
"Sign": "",
"Signs": {
"ID": "",
"_": "",
"Language": "IT"
}
},
"Name": {
"Value": "Tipi schede di memoria",
"Language": "IT"
}
}
}
]
}
]
Here i loop my initial objects (this.compare_products) to extract, in two arrays (featureGroupIds - featureIds) the ID of my block and the CategoryFeatureId
let featureGroupIds = []
let featureIds = []
this.compare_products.forEach((object) => {
featureGroupIds = featureGroupIds.concat(FeaturesGroups.map(o => o.ID))
featureIds = featureIds.concat(FeaturesGroups.map(o => o.Features.map(o => o. CategoryFeatureId))).flat(2)
})
The two arrays, featureGroupIds and featureIds are now filled with every block ID and every CategoryFeatureId present in my four object.
Now I have to filter the object I call "structure" to remove the block and the features with an ID that is not present in my arrays.
This is my structure, and as you can see is similar.
[
{
"name": "Display",
"data": {
"id": 34566,
"category_id": 2647
},
"features": [
{
"name": "Tipo di display",
"data": {
"id": 85325,
"category_id": 2647,
"feature_id": 9104,
"category_feature_group_id": 34566,
"order": 10100140
}
},
{
"name": "Touch screen",
"data": {
"id": 85331,
"category_id": 2647,
"feature_id": 4963,
"category_feature_group_id": 34566,
"order": 10100129
}
},
{
"name": "Dimensioni schermo",
"data": {
"id": 158002,
"category_id": 2647,
"feature_id": 3544,
"category_feature_group_id": 34566,
"order": 100149
}
},
{
"name": "à di Pixel",
"data": {
"id": 85347,
"category_id": 2647,
"feature_id": 13246,
"category_feature_group_id": 34566,
"order": 100147
}
},
{
"name": "Tipo di vetro",
"data": {
"id": 94704,
"category_id": 2647,
"feature_id": 7610,
"category_feature_group_id": 34566,
"order": 100050
}
}
]
},
{
"name": "Altre caratteristiche",
"data": {
"id": 34569,
"category_id": 2647,
"feature_group_id": 146,
"name": null,
"order": 0
},
"features": [
{
"name": "inside",
"data": {
"id": 110410,
"category_id": 2647,
"feature_id": 18688,
"category_feature_group_id": 34569,
"order": 100000
}
}
]
}
]
Here is my function
structure = structure.filter(featureGroup => this.featureGroupIds.includes(featureGroup.data.id));
structure.map((object) => {
object.features.filter(feature => this.featureIds.includes(feature.data.feature_id))
})
this.featureIds and this.featureGroupIds are the array with the group IDS and with the feature IDS.
Is there a more efficient way to do this?

How to correctly use JSON.parse()? JSON result is not valid

When I use JSON.parse(myJSONString) the result is not a valid JSON file. I'm in an nodejs environment. Any Ideas what I can fix in my code? I user XML2JS to converte an XML Api call to JS.
I have printed out the results and already dived deeper into JSON.parse but didn't find further information...
exports.getStations = functions.https.onCall(async (data) => {
let stations
await axios.get(encodeURI(`XMLAPi`))
.then(async (response) => {
parseString(response.data, (err, result) => {
stations = JSON.stringify(result)
console.log(stations) //First console.log
})
})
.catch((error) => {
console.log(error)
})
console.log(JSON.parse(stations)) //Second console.log
return JSON.parse(stations)
})
Result for first console.log (valid JSON but String):
{"itdRequest":{"$":{"xsi:noNamespaceSchemaLocation":"itd.xsd","language":"DE","sessionID":"EfaOpenServiceT_2882840828","client":"axios/0.19.0","serverID":"EfaOpenServiceT_","clientIP":"127.0.0.1","version":"10.3.5.46","virtDir":"static02","xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance"},"itdStopFinderRequest":{"$":{"requestID":"1"},"itdOdv":{"$":{"type":"any","usage":"sf","anyObjFilter":"42"},"itdOdvPlace":{"$":{"state":"empty"},"odvPlaceElem":""},"itdOdvName":{"$":{"state":"list"},"itdMessage":{"$":{"type":"error","module":"BROKER","code":"-8011"}},"odvNameElem":[{"_":"Mettmann, Stadtwald S","$":{"value":"0:1","selected":"1","listIndex":"0","streetName":"","omc":"5158024","placeID":"5","x":"6987248.99348","y":"51250980.94198","mapName":"WGS84","id":"20019083","anyType":"stop","anyTypeSort":"2","nameKey":"","locality":"Mettmann","postCode":"","objectName":"Stadtwald S","buildingName":"","buildingNumber":"","matchQuality":"235","stateless":"20019083"}},{"_":"Mettmann, ME-Zentrum S","$":{"value":"1:2","selected":"0","listIndex":"1","streetName":"","omc":"5158024","placeID":"5","x":"6979002.45917","y":"51249372.83702","mapName":"WGS84","id":"20019020","anyType":"stop","anyTypeSort":"2","nameKey":"","locality":"Mettmann","postCode":"","objectName":"ME-Zentrum S","buildingName":"","buildingNumber":"","matchQuality":"234","stateless":"20019020"}},{"_":"Mettmann, Neanderthal S","$":{"value":"2:3","selected":"0","listIndex":"2","streetName":"","omc":"5158024","placeID":"5","x":"6953346.57466","y":"51227837.93128","mapName":"WGS84","id":"20019191","anyType":"stop","anyTypeSort":"2","nameKey":"","locality":"Mettmann","postCode":"","objectName":"Neanderthal S","buildingName":"","buildingNumber":"","matchQuality":"234","stateless":"20019191"}}],"odvNameInput":"mettmann"},"genAttrList":{"genAttrElem":[{"name":"anyObjFilter","value":"STOP"},{"name":"anyObjFilter","value":"ADDRESS"},{"name":"anyObjFilter","value":"POI"}]}},"itdDateTime":{"$":{"ttpFrom":"20190601","ttpTo":"20191231"},"itdDate":{"$":{"day":"10","month":"8","year":"2019","weekday":"7"}},"itdTime":{"$":{"hour":"16","minute":"4"}}}}}}
Result for second console.log (invalid JSON after parse):
Object {
"data": Object {
"itdRequest": Object {
"$": Object {
"client": "axios/0.19.0",
"clientIP": "127.0.0.1",
"language": "DE",
"serverID": "EfaOpenServiceT_",
"sessionID": "EfaOpenServiceT_2882840828",
"version": "10.3.5.46",
"virtDir": "static02",
"xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
"xsi:noNamespaceSchemaLocation": "itd.xsd",
},
"itdStopFinderRequest": Object {
"$": Object {
"requestID": "1",
},
"itdDateTime": Object {
"$": Object {
"ttpFrom": "20190601",
"ttpTo": "20191231",
},
"itdDate": Object {
"$": Object {
"day": "10",
"month": "8",
"weekday": "7",
"year": "2019",
},
},
"itdTime": Object {
"$": Object {
"hour": "16",
"minute": "4",
},
},
},
"itdOdv": Object {
"$": Object {
"anyObjFilter": "42",
"type": "any",
"usage": "sf",
},
"genAttrList": Object {
"genAttrElem": Array [
Object {
"name": "anyObjFilter",
"value": "STOP",
},
Object {
"name": "anyObjFilter",
"value": "ADDRESS",
},
Object {
"name": "anyObjFilter",
"value": "POI",
},
],
},
"itdOdvName": Object {
"$": Object {
"state": "list",
},
"itdMessage": Object {
"$": Object {
"code": "-8011",
"module": "BROKER",
"type": "error",
},
},
"odvNameElem": Array [
Object {
"$": Object {
"anyType": "stop",
"anyTypeSort": "2",
"buildingName": "",
"buildingNumber": "",
"id": "20019083",
"listIndex": "0",
"locality": "Mettmann",
"mapName": "WGS84",
"matchQuality": "235",
"nameKey": "",
"objectName": "Stadtwald S",
"omc": "5158024",
"placeID": "5",
"postCode": "",
"selected": "1",
"stateless": "20019083",
"streetName": "",
"value": "0:1",
"x": "6987248.99348",
"y": "51250980.94198",
},
"_": "Mettmann, Stadtwald S",
},
Object {
"$": Object {
"anyType": "stop",
"anyTypeSort": "2",
"buildingName": "",
"buildingNumber": "",
"id": "20019020",
"listIndex": "1",
"locality": "Mettmann",
"mapName": "WGS84",
"matchQuality": "234",
"nameKey": "",
"objectName": "ME-Zentrum S",
"omc": "5158024",
"placeID": "5",
"postCode": "",
"selected": "0",
"stateless": "20019020",
"streetName": "",
"value": "1:2",
"x": "6979002.45917",
"y": "51249372.83702",
},
"_": "Mettmann, ME-Zentrum S",
},
Object {
"$": Object {
"anyType": "stop",
"anyTypeSort": "2",
"buildingName": "",
"buildingNumber": "",
"id": "20019191",
"listIndex": "2",
"locality": "Mettmann",
"mapName": "WGS84",
"matchQuality": "234",
"nameKey": "",
"objectName": "Neanderthal S",
"omc": "5158024",
"placeID": "5",
"postCode": "",
"selected": "0",
"stateless": "20019191",
"streetName": "",
"value": "2:3",
"x": "6953346.57466",
"y": "51227837.93128",
},
"_": "Mettmann, Neanderthal S",
},
],
"odvNameInput": "mettmann",
},
"itdOdvPlace": Object {
"$": Object {
"state": "empty",
},
"odvPlaceElem": "",
},
},
},
},
},
}
You are already converting to string as a parsestring function. But it's also converting to JSON.stringify().
You can try check this value
let stations = await axios.get(encodeURI(`XMLAPi`));
console.log(JSON.stringify(stations.data)) // What is value??

Convert Leaf Nodes Into Child under Child for Json Object In D3js tree

The Overall Context is to find the leaf node of every parent(x) and children(x1) if there are more than 2 leaf nodes make them the child's as one under another
I Tried to use loadash in Nodejs but I was unable to get the expected result
I have a JSON Data
{
"Id": "1",
"name": "x",
"parent": "",
"children": [{
"Id": "2",
"name": "x1",
"parent": "1",
"children": [{
"Id": "3",
"name": "x2",
"parent": "2"
}, {
"Id": "4",
"name": "x3",
"parent": "2"
},
{
"Id": "5",
"name": "x4",
"parent": "2"
},
{
"Id": "6",
"name": "x5",
"parent": "2"
},
{
"Id": "7",
"name": "x6",
"parent": "2"
},
{
"Id": "8",
"name": "x7",
"parent": "2"
}
]
},
{
"Id": "9",
"name": "x8",
"parent": "1"
},
{
"Id": "10",
"name": "x10",
"parent": "1"
}, {
"Id": "11",
"name": "x9",
"parent": "1"
},
{
"Id": "12",
"name": "x11",
"parent": "1"
}
]
}
I would like to change into the below format
{
"Id": "1",
"name": "x",
"parent": "",
"children": [{
"Id": "2",
"name": "x1",
"parent": "1",
"children": [{
"Id": "3",
"name": "x2",
"IC": "Yes",
"parent": "2",
"children": [{
"Id": "5",
"name": "x4",
"IC": "Yes",
"parent": "2",
"children": [{
"Id": "7",
"parent": "2",
"name": "x6"
}]
}]
},
{
"Id": "4",
"name": "x3",
"IC": "Yes",
"parent": "2",
"children": [{
"Id": "5",
"name": "x5",
"IC": "Yes",
"parent": "2",
"children": [{
"Id": "7",
"name": "x7",
"IC": "Yes",
"parent": "2"
}]
}]
}
]
},
{
"Id": "9",
"name": "x8",
"parent": "1",
"children": [{
"Id": "10",
"name": "x10",
"IC": "Yes",
"parent": "1"
}]
},
{
"Id": "11",
"name": "x9",
"parent": "1",
"children": [{
"Id": "11",
"name": "x11",
"parent": "1",
"IC": "Yes"
}]
}
]
}
Note:
1. If there are 8 leaf nodes it should be split 4+4,
2. If there are 9 leaf nodes it should be split 5+4,
3. In the same way, If it has 13 it can be split into 7+6.
any help would be appreciated
thanks in advance
The following code will take all leaf nodes and create 2 even branches from them. The output is not identical to yours, but you mention in your comments that the branches can be built randomly from the leaf nodes, and this code respects that requirement.
const input = {
"name": "x",
"children": [
{
"name": "x1",
"children": [
{
"name": "x2"
},
{
"name": "x3"
},
{
"name": "x4"
},
{
"name": "x5"
},
{
"name": "x6"
},
{
"name": "x7"
}
]
},
{
"name": "x8"
},
{
"name": "x10"
},
{
"name": "x9"
},
{
"name": "x11"
}
]
};
function cutLeafNodes(node){
if(!node.children){
return;
}
const leaves = [];
const branches = [];
node.children.forEach(child => {
if(child.children){
branches.push(child);
} else {
leaves.push(child);
}
});
node.children = branches;
return leaves;
}
function reorderLeaves(nodes){
if(!nodes){
return;
}
const midpoint = nodes.length / 2;
const newChildren = [];
newChildren.push(createAncestry(nodes.splice(0, midpoint)));
newChildren.push(createAncestry(nodes));
return newChildren;
}
function createAncestry(nodes){
let currentChild = nodes[0];
const firstChild = currentChild;
for (let i = 1; i < nodes.length; i++) {
currentChild.children = [nodes[i]];
currentChild = currentChild.children[0];
}
return firstChild;
}
function reorganizeTree(node){
const leaves = cutLeafNodes(node);
if(node.children){
node.children.forEach(child => {
reorganizeTree(child);
});
}
if(leaves){
const newBranches = reorderLeaves(leaves);
newBranches.forEach(branch =>{
node.children.push(branch);
})
}
return node;
}
const output = reorganizeTree(input);
console.debug(output);

How do I filter an array of data by id or name using another array of data to display in React Table?

I have a role-template array that gives each role a name, and a description. It also has a nested object with an array of permissions that are identified by id.
{
"data": [
{
"id": "1",
"type": "role-templates",
"attributes": {
"name": "Org Admin"
},
"relationships": {
"permissions": {
"data": [
{ "type": "permissions", "id": "1" },
{ "type": "permissions", "id": "2" },
{ "type": "permissions", "id": "3" },
{ "type": "permissions", "id": "4" },
{ "type": "permissions", "id": "5" },
{ "type": "permissions", "id": "6" },
{ "type": "permissions", "id": "7" },
{ "type": "permissions", "id": "8" },
{ "type": "permissions", "id": "9" },
{ "type": "permissions", "id": "10" },
{ "type": "permissions", "id": "11" },
{ "type": "permissions", "id": "12" },
{ "type": "permissions", "id": "13" },
{ "type": "permissions", "id": "14" },
{ "type": "permissions", "id": "15" },
{ "type": "permissions", "id": "17" },
{ "type": "permissions", "id": "18" },
{ "type": "permissions", "id": "19" },
{ "type": "permissions", "id": "20" },
{ "type": "permissions", "id": "21" },
{ "type": "permissions", "id": "23" },
{ "type": "permissions", "id": "24" }
]
}
}
},
{
"id": "2",
"type": "role-templates",
"attributes": { "name": "Data Admin" },
"relationships": {
"permissions": {
"data": [
{ "type": "permissions", "id": "1" },
{ "type": "permissions", "id": "2" },
{ "type": "permissions", "id": "3" },
{ "type": "permissions", "id": "4" },
{ "type": "permissions", "id": "5" },
{ "type": "permissions", "id": "6" }
]
}
}
},
{
"id": "3",
"type": "role-templates",
"attributes": {
"name": "Setup Admin"
},
"relationships": {
"permissions": {
"data": [{ "type": "permissions", "id": "8" }]
}
}
},
{
"id": "4",
"type": "role-templates",
"attributes": { "name": "Data Consumer"},
"relationships": {
"permissions": {
"data": [
{ "type": "permissions", "id": "11" },
{ "type": "permissions", "id": "13" }
]
}
}
},
{
"id": "5",
"type": "role-templates",
"attributes": { "name": "APT User" },
"relationships": {
"permissions": {
"data": [
{ "type": "permissions", "id": "17" },
{ "type": "permissions", "id": "18" },
{ "type": "permissions", "id": "19" }
]
}
}
},
{
"id": "6",
"type": "role-templates",
"attributes": {
"name": "User Admin"
},
"relationships": {
"permissions": {
"data": [
{ "type": "permissions", "id": "21" },
{ "type": "permissions", "id": "23" }
]
}
}
}
],
"meta": { "record-count": 6 }
}
Now I have a permissions array that gives each permission a name, and an id. That id can be matched to the nested array in the role-template array. I want to match these two arrays by the permission.id property that each of these arrays posses. Then for each role that has a permission. I want to display an asterisk * for this
How can I do that?
[
{
"id": "1",
"type": "permissions",
"attributes": {
"name": "Administer Source List",
},
"relationships": {
"roles": {
"data": [
{ "type": "roles", "id": "1" },
{ "type": "roles", "id": "2" },
{ "type": "roles", "id": "7" },
{ "type": "roles", "id": "8" }
]
}
}
},
{
"id": "2",
"type": "permissions",
"attributes": {
"name": "Administer Common Layers",
},
"relationships": {
"roles": {
"data": [
{ "type": "roles", "id": "1" },
{ "type": "roles", "id": "2" },
{ "type": "roles", "id": "7" },
{ "type": "roles", "id": "8" }
]
}
}
},
{
"id": "3",
"type": "permissions",
"attributes": {
"name": "Do benchmark tagging"
},
"relationships": {
"roles": {
"data": [
{ "type": "roles", "id": "1" },
{ "type": "roles", "id": "2" },
{ "type": "roles", "id": "7" },
{ "type": "roles", "id": "8" }
]
}
}
},
{
"id": "4",
"type": "permissions",
"attributes": {
"name": "Do trend mapping"
},
"relationships": {
"roles": {
"data": [
{ "type": "roles", "id": "1" },
{ "type": "roles", "id": "2" },
{ "type": "roles", "id": "7" },
{ "type": "roles", "id": "8" }
]
}
}
},
{
"id": "5",
"type": "permisns",
"attributes": {
"name": "Map custom values (for each data source)"
},
"relationships": {
"roles": {
"data": [
{ "type": "roles", "id": "1" },
{ "type": "roles", "id": "2" },
{ "type": "roles", "id": "7" },
{ "type": "roles", "id": "8" }
]
}
}
},
{
"id": "6",
"type": "permissions",
"attributes": {
"name": "Administer Data Sets"
},
"relationships": {
"roles": {
"data": [
{ "type": "roles", "id": "1" },
{ "type": "roles", "id": "2" },
{ "type": "roles", "id": "7" },
{ "type": "roles", "id": "8" }
]
}
}
},
{
"id": "7",
"type": "permisns"
"attributes": {
"name": "Create Campaigns"
},
"relationships": {
"roles": {
"data": [{ "type": "roles", "id": "1" }, { "type": "roles", "id": "7" }]
}
}
},
{
"id": "8",
"type": "permissions",
"attributes": {
"name": "Access/modify campaign setup"
},
"relationships": {
"roles": {
"data": [
{ "type": "roles", "id": "1" },
{ "type": "roles", "id": "3" },
{ "type": "roles", "id": "7" },
{ "type": "roles", "id": "9" }
]
}
}
},
{
"id": "9",
"type": "permissions",
"attributes": {
"name": "Launch campaigns"
},
"relationships": {
"roles": {
"data": [{ "type": "roles", "id": "1" }, { "type": "roles", "id": "7" }]
}
}
},
{
"id": "10",
"type": "permissions",
"attributes": {
"name": "Create org-wide survey-related notifications"
},
"relationships": {
"roles": {
"data": [{ "type": "roles", "id": "1" }, { "type": "roles", "id": "7" }]
}
}
},
{
"id": "11",
"type": "permissions",
"attributes": {
"name": "View Reports"
},
"relationships": {
"roles": {
"data": [
{ "type": "roles", "id": "1" },
{ "type": "roles", "id": "4" },
{ "type": "roles", "id": "7" },
{ "type": "roles", "id": "10" }
]
}
}
},
{
"id": "12",
"type": "permissions",
"attributes": {
"name": "Modify prebuilt reports"
},
"relationships": {
"roles": {
"data": [{ "type": "roles", "id": "1" }, { "type": "roles", "id": "7" }]
}
}
},
{
"id": "13",
"type": "permissions",
"attributes": {
"name": "Create new reports"
},
"relationships": {
"roles": {
"data": [
{ "type": "roles", "id": "1" },
{ "type": "roles", "id": "4" },
{ "type": "roles", "id": "7" },
{ "type": "roles", "id": "10" }
]
}
}
},
{
"id": "14",
"type": "permissions",
"attributes": {
"name": "Share reports with rest of org"
},
"relationships": {
"roles": {
"data": [{ "type": "roles", "id": "1" }, { "type": "roles", "id": "7" }]
}
}
},
{
"id": "15",
"type": "permissions",
"attributes": {
"name": "Share filters with rest of org"
},
"relationships": {
"roles": {
"data": [{ "type": "roles", "id": "1" }, { "type": "roles", "id": "7" }]
}
}
},
{
"id": "16",
"type": "permissions",
"attributes": {
"name": "Create portfolio"
},
"relationships": {
"roles": {
"data": []
}
}
},
{
"id": "17",
"type": "permissions",
"attributes": {
"name": "Access all portfolios (at org)"
},
"relationships": {
"roles": {
"data": [
{ "type": "roles", "id": "1" },
{ "type": "roles", "id": "5" },
{ "type": "roles", "id": "7" },
{ "type": "roles", "id": "11" }
]
}
}
},
{
"id": "18",
"type": "permissions",
"attributes": {
"name": "Assign action plans"
},
"relationships": {
"roles": {
"data": [
{ "type": "roles", "id": "1" },
{ "type": "roles", "id": "5" },
{ "type": "roles", "id": "7" },
{ "type": "roles", "id": "11" }
]
}
}
},
{
"id": "19",
"type": "permissions",
"attributes": {
"name": "Work on action plans"
},
"relationships": {
"roles": {
"data": [
{ "type": "roles", "id": "1" },
{ "type": "roles", "id": "5" },
{ "type": "roles", "id": "7" },
{ "type": "roles", "id": "11" }
]
}
}
},
{
"id": "20",
"type": "permissions",
"attributes": {
"name": "Administer role templates for org"
},
"relationships": {
"roles": {
"data": [{ "type": "roles", "id": "1" }, { "type": "roles", "id": "7" }]
}
}
},
{
"id": "21",
"type": "permissions",
"attributes": {
"name": "Add/edit/delete non org-admin users at org"
},
"relationships": {
"roles": {
"data": [
{ "type": "roles", "id": "1" },
{ "type": "roles", "id": "6" },
{ "type": "roles", "id": "7" },
{ "type": "roles", "id": "12" }
]
}
}
},
{
"id": "22",
"type": "permissions",
"attributes": {
"name": "Add/edit/dete ORg Admin users at org"
},
"relationships": {
"roles": {
"data": []
}
}
},
{
"id": "23",
"type": "permissions",
"attributes": {
"name": "Administer access patterns at org"
},
"relationships": {
"roles": {
"data": [
{ "type": "roles", "id": "1" },
{ "type": "roles", "id": "6" },
{ "type": "roles", "id": "7" },
{ "type": "roles", "id": "12" }
]
}
}
},
{
"id": "24",
"type": "permissions",
"attributes": {
"name": "Switch user (\"Impersonate\" another user)"
},
"relationships": {
"roles": {
"data": [{ "type": "roles", "id": "1" }, { "type": "roles", "id": "7" }]
}
}
}
]
My react table looks like this right now:
What I want to do is to put an asterisk * in every cell for the permission that each role has.
My React component currently looks like this:
class SystemRoleTemplatesContainer extends React.Component {
constructor(props) {
super(props);
this.state = {
isLoading: false,
permissionList: [],
roleTemplateList: [],
permissionsGroup: []
};
}
componentDidMount = () => {
this.getTableData();
}
getTableData = () => {
store.dispatch(api.getRoletemplates()).then((result) => {
const permissionHeader = [{
Header: "Permissions",
accessor: "permission"
}]
const roleTemplateItems = result.body.data.map((data) => {
return {
id: data.relationships.permissions.data.map((data)=>{
return {
id: data.id
}
}),
Header: data.attributes.name,
accessor: data.attributes.name.replace(/\s/g, '')
}
});
const roleTemplate = permissionHeader.concat(roleTemplateItems)
this.setState(() => ({
"roleTemplateList": roleTemplate
}));
});
store.dispatch(api.getPermissions()).then((result) => {
const permissionItems = result.body.data.map((data) => {
return {
id: data.id,
permission: data.attributes.name
}
});
this.setState(() => ({
"permissionList": permissionItems
}));
});
}
render() {
const {isLoading,roleTemplateList, permissionList} = this.state;
if (isLoading) {
return <LoadingAnimation />;
}
return (
<div className="role-management-form">
<div className="admin-user-container-title">
<Row>
<Col md={8}>
<h3>Manage Roles Template for System</h3>
</Col>
</Row>
</div>
<Table
columns={roleTemplateList}
className="organization-tbl"
data={permissionList}
defaultPageSize={50}
minRows={0}
/>
</div>
);
}
}
So I was able to use lodash to accomplish this.
class SystemRoleTemplatesContainer extends React.Component {
constructor(props) {
super(props);
this.state = {
isLoading: false,
permissionList: [],
roleTemplateList: []
};
}
componentDidMount = () => {
this.getTableData();
}
getTableData = () => {
store.dispatch(api.getRoletemplates()).then((result) => {
const permissionHeader = [{
Header: "Permissions",
accessor: "permission"
}]
const roleTemplateItems = result.body.data.map((data) => {
return {
id: data.relationships.permissions.data.map((data)=>{
return {
id: data.id
}
}),
Header: data.attributes.name,
accessor: data.attributes.name.replace(/\s/g, '')
}
});
const roleTemplate = permissionHeader.concat(roleTemplateItems)
this.setState(() => ({
"roleTemplateList": roleTemplate
}));
});
store.dispatch(api.getPermissions()).then((result) => {
const permissionItems = result.body.data.map((data) => {
return {
id: data.id,
permission: data.attributes.name
}
});
this.setState(() => ({
"permissionList": permissionItems
}));
});
}
render() {
const {isLoading,roleTemplateList, permissionList} = this.state;
const updatedList = permissionList.map(permission => {
return roleTemplateList.reduce((permAcc, role) => {
const match = _.find(role.id, {'id': permAcc.id});
if(typeof match !== 'undefined' && role.accessor !== 'permission') {
permAcc[role.accessor] = '*';
} else if(role.accessor !== 'permission') {
permAcc[role.accessor] = '';
}
return permAcc;
}, permission);
});
if (isLoading) {
return <LoadingAnimation />;
}
return (
<div className="role-management-form">
<div className="admin-user-container-title">
<Row>
<Col md={8}>
<h3>Manage Roles Template for System</h3>
</Col>
</Row>
</div>
<Table
columns={roleTemplateList}
className="organization-tbl"
data={updatedList}
defaultPageSize={50}
minRows={0}
/>
</div>
);
}
}

Nested Loops in angularjs

I have been using nested loops to access data of the json object to display the id and type of topping, however its not working. Here's my code:
var j_obj = {
"id": "0001",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"batters": {
"batter": [{
"id": "1001",
"type": "Regular"
}, {
"id": "1002",
"type": "Chocolate"
}, {
"id": "1003",
"type": "Blueberry"
}, {
"id": "1004",
"type": "Devil's Food"
}]
},
"topping": [{
"id": "5001",
"type": "None"
}, {
"id": "5002",
"type": "Glazed"
}, {
"id": "5005",
"type": "Sugar"
}, {
"id": "5007",
"type": "Powdered Sugar"
}, {
"id": "5006",
"type": "Chocolate with Sprinkles"
}, {
"id": "5003",
"type": "Chocolate"
}, {
"id": "5004",
"type": "Maple"
}]
}
var Outer_log=[];
debugger
angular.forEach(j_obj, function(an_object){
//Outer_log.push("ID : "+an_object.id+" type : "+an_object.type);
angular.forEach(an_object.topping,function(innerobject){
Outer_log.push("ID : "+innerobject.id+" type : "+innerobject.type);
},Outer_log);
});
console.log(Outer_log);
Could someone please highlight the error in above code, Thanks
Without using nested loop you can iterate using angular.forEach like this
var finalArray=[];
angular.forEach(j_obj[0].topping, function(eachobject){
finalArray.push("ID : "+ eachobject.id+" type : "+ eachobject.type);
});
Angulars forEach is intended to iterate over arrays not object. so if you change your code to something like this
var j_obj = [{ ...}] //object is wrapped inside array.
it will work. Another thing is you don't need a nested loop in this case. You can just do:
angular.forEach(j_obj.topping, function(key, value){ ... });
you are iterating over object where as loop run over array.
hope this helps JSfiddle link
var j_obj = [{
"id": "0001",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"batters": {
"batter": [{
"id": "1001",
"type": "Regular"
}, {
"id": "1002",
"type": "Chocolate"
}, {
"id": "1003",
"type": "Blueberry"
}, {
"id": "1004",
"type": "Devil's Food"
}]
},
"topping": [{
"id": "5001",
"type": "None"
}, {
"id": "5002",
"type": "Glazed"
}, {
"id": "5005",
"type": "Sugar"
}, {
"id": "5007",
"type": "Powdered Sugar"
}, {
"id": "5006",
"type": "Chocolate with Sprinkles"
}, {
"id": "5003",
"type": "Chocolate"
}, {
"id": "5004",
"type": "Maple"
}]
}]
var Outer_log = [];
angular.forEach(j_obj, function(an_object) {
//Outer_log.push("ID : "+an_object.id+" type : "+an_object.type);
angular.forEach(an_object.topping, function(innerobject) {
Outer_log.push("ID : " + innerobject.id + " type : " + innerobject.type);
}, Outer_log);
});
console.log(Outer_log);

Categories