How to replace all the values in JSON structure using javascript? - javascript

If I have JSON structure like this, I want to parse this JSON replace all values with '{param.keyName}', if the key value is array of objects than need to generate its value like {param.headKey[index]keyName}
{
"resources": [
{
"name": "prod",
"type": "local",
"properties": {
"zone": "asia",
"disks": [
{
"sizeGb": 3,
"diskType": "boot",
"name": "backup"
},
{
"sizeGb": 4,
"diskType": "ssd",
"name": "cache"
}
]
}
}
]
}
The output of the function should be JSON like this where all the values should be replaced with the mapping. If there is any array of objects than it should prefixed by array index like {param.disks0_name}, where disks is an array of objects.
{
"resources": [
{
"name": "prod",
"type": "local",
"properties": {
"zone": "{param.zone}",
"disks": [
{
"sizeGb": '{param.disks0_sizeGb}',
"diskType": '{param.disks0_diskType}',
"name": "{param.disks0_name}"
},
{
"sizeGb": '{param.disks1_zone}',
"diskType": '{param.disks1_diskType}',
"name": "{param.disks1_name}"
}
]
}
}
]
}

You could look for the arrays/objects and iterate them for getting the path for the last property.
Format as desired (which is unclear for nested arrays).
function formatPath(path) {
return `{${path.join('.')}}`;
}
function getPath(object, path = []) {
return Object.assign(
Array.isArray(object) ? [] : {},
...Object.entries(object).map(([k, v]) => ({
[k]: v && typeof v === 'object'
? getPath(v, path.concat(k))
: formatPath(path.concat(k))
}))
);
}
var data = { resources: [{ name: "prod", type: "local", properties: { zone: "asia", disks: [{ sizeGb: 3, diskType: "boot", name: "backup" }, { sizeGb: 4, diskType: "ssd", name: "cache" }] } }] };
data = { resources: data.resources.map(o => Object.assign({}, o, { properties: getPath(o.properties, ['param']) })) };
console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }
ES5
function formatPath(path) {
return '{' + path.join('.') + '}';
}
function getPath(object, path) {
path = path || [];
return Object.keys(object).reduce(
function (r, k) {
r[k] = object[k] && typeof object[k] === 'object'
? getPath(object[k], path.concat(k))
: formatPath(path.concat(k));
return r;
},
Array.isArray(object) ? [] : {}
);
}
var data = { resources: [{ name: "prod", type: "local", properties: { zone: "asia", disks: [{ sizeGb: 3, diskType: "boot", name: "backup" }, { sizeGb: 4, diskType: "ssd", name: "cache" }] } }] };
data = { resources: data.resources.map(function (o) {
return Object.keys(o).reduce(function (r, k) {
r[k] = k === 'properties'
? getPath(o.properties, ['param'])
: o[k];
return r;
}, {});
}) };
console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Related

Flatten JSON objects in JavaScript

I have a JSON response and I need to flatten some objects according to conditions.
In my case, the condition is if object === "$"
I also need to flatten some array to string only. What is the best way to manage this? Any lib recommendations?
The final goal would be to use it as a GraphQL schema.
The JSON response is:
[
{
"$":{
"product_id":"110015888426488829026466000222",
"name":"Belstaff Trialmaster Pro W Motorradjacke Schwarz",
"sku_number":"B000134394",
"manufacturer_name":"BELSTAFF",
"part_number":"42050011L81N03379005436"
},
"discount":[
{
"$":{
"currency":"EUR"
},
"type":[
"amount"
]
}
],
"price":[
{
"$":{
"currency":"EUR"
},
"sale":[
"1195.00"
],
"retail":[
"1195.00"
]
}
],
"shipping":[
{
"cost":[
{
"$":{
"currency":"EUR"
},
"amount":[
"0.00"
],
"currency":[
"EUR"
]
}
],
"information":[
"3–7 Werktage"
],
"availability":[
"in-stock"
]
}
],
"attributeClass":[
{
"$":{
"class_id":"60"
},
"Product_Type":[
"Motorcycle"
],
"Size":[
"36,38,40,42,44,46,48"
],
"Material":[
"Waxed Leather"
],
"Color":[
"Schwarz"
],
"Gender":[
"Female"
],
"Age":[
"Adult"
]
}
]
},
...
]
And I want
[
{
"product_id":"110015888426488829026466000222",
"name":"Belstaff Trialmaster Pro W Motorradjacke Schwarz",
"sku_number":"B000134394",
"manufacturer_name":"BELSTAFF",
"part_number":"42050011L81N03379005436"
"discount":{
"currency":"EUR"
"type":"amount"
},
"price":{
"currency": "EUR",
"sale": "1195.00",
"retail": "1195.00"
},
"shipping":[
"cost":{
"currency": "EUR"
"amount": "0.00",
"currency": "EUR"
},
"information":"3–7 Werktage",
"availability": "in-stock"
],
"attributeClass":{
"class_id":"60",
"Product_Type": "Motorcycle",
"Size": "36,38,40,42,44,46,48",
"Material": "Waxed Leather",
"Color": "Schwarz",
"Gender": "Female",
"Age": "Adult"
}
},
...
]
What I tried:
const flatJson = async data => {
try {
const newData = await Promise.all(json.map( async (item, i) => {
xxx
}));
return newData
}
catch(err) {
console.log(err)
}
};
You could convert the various types to single objects.
const convert = object => {
if (!object || typeof object !== 'object') return object;
if (Array.isArray(object)) {
return object.every(v => typeof v === 'string')
? object.join()
: Object.assign({}, ...object.map(convert));
}
return Object.fromEntries(Object.entries(object).flatMap(([k, v]) =>
k === '$'
? Object.entries(v).map(([k, v]) => [k, convert(v)])
: [[k, convert(v)]]
));
};
var data = [{ $: { product_id: "110015888426488829026466000222", name: "Belstaff Trialmaster Pro W Motorradjacke Schwarz", sku_number: "B000134394", manufacturer_name: "BELSTAFF", part_number: "42050011L81N03379005436" }, discount: [{ $: { currency: "EUR" }, type: ["amount"] }], price: [{ $: { currency: "EUR" }, sale: ["1195.00"], retail: ["1195.00"] }], shipping: [{ cost: [{ $: { currency: "EUR" }, amount: ["0.00"], currency: ["EUR"] }], information: ["3–7 Werktage"], availability: ["in-stock"] }], attributeClass: [{ $: { class_id: "60" }, Product_Type: ["Motorcycle"], Size: ["36,38,40,42,44,46,48"], Material: ["Waxed Leather"], Color: ["Schwarz"], Gender: ["Female"], Age: ["Adult"] }] }],
result = data.map(convert);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can try this recursion code
function recurseData(data, level) {
var newdata = {};
for(var prop in data) {
if( data[prop].constructor == Object && prop=="$") {
var data1 = recurseData(data[prop], level+1);
for(var prop1 in data1)
newdata[prop1] = data1[prop1];
}
else if(data[prop].constructor == Object){
newdata[prop] = recurseData(data[prop],level+1);
}
else if(data[prop].constructor == Array && level > 0 && data[prop][0].constructor != Object && data[prop].length==1){
newdata[prop] = data[prop][0];
}
else if(data[prop].constructor == Array) {
newdata[prop] = [];
for(var i=0;i<data[prop].length;i++)
newdata[prop].push( recurseData(data[prop][i],level+1) );
}
else if(prop!="$")
newdata[prop] = data[prop];
}
return newdata;
}
data[0] = recurseData(data[0], 0);
is simple loops through all tree structure and detects for a key $

Es6 way to convert object key value to one single object

I want to convert all data into one object,
let d = {
"Coupon_Code": "code",
"Coupon_Name": "namie",
"Coupon_Desc": 1000,
"selectedCity": [
{
"Coupon_City_Name": "xyz"
}
],
"selectedCategory": [
{
"Coupon_Category_Name": "Shopping"
}
],
"selectedCompany": [
{
"Coupon_Company_Name": "Shopper Stop"
}
],
"selectedState": [
{
"Coupon_State_Name": "abc"
}
],
"Coupon_Date": "2222-02-22",
}
i tried some methods of Object like keys , entries but dont no what to use.
Final output should be
let d = {
Coupon_Code: "code",
Coupon_Name: "namie",
Coupon_Desc: 1000,
Coupon_City_Name: "xyz",
Coupon_Category_Name: "Shopping",
Coupon_Company_Name: "Shopper Stop",
Coupon_State_Name: "abc",
Coupon_Date: "2222-02-22",
};
what's the best and optimum way to have above result using Venila Js and Es6
Reduce the entries of the original object. If the entry's value is an array merge the 1st element, if not merge the original key and value. You can merge the properties into the object using object spread:
const data = {"Coupon_Code":"code","Coupon_Name":"namie","Coupon_Desc":1000,"selectedCity":[{"Coupon_City_Name":"xyz"}],"selectedCategory":[{"Coupon_Category_Name":"Shopping"}],"selectedCompany":[{"Coupon_Company_Name":"Shopper Stop"}],"selectedState":[{"Coupon_State_Name":"abc"}],"Coupon_Date":"2222-02-22"};
const result = Object.entries(data)
.reduce((r, [k, v]) => ({
...r,
...Array.isArray(v) ? v[0] : { [k]: v }
}), {});
console.log(result);
You can use Array.reduce and Object.entries
let d = {"Coupon_Code":"code","Coupon_Name":"namie","Coupon_Desc":1000,"selectedCity":[{"Coupon_City_Name":"xyz"}],"selectedCategory":[{"Coupon_Category_Name":"Shopping"}],"selectedCompany":[{"Coupon_Company_Name":"Shopper Stop"}],"selectedState":[{"Coupon_State_Name":"abc"}],"Coupon_Date":"2222-02-22"};
d = Object.entries(d).reduce((a,[k,v]) => {
// If the value is an array, iterate over it to merge into the resultant object
if(Array.isArray(v)) Object.assign(a, ...v)
else Object.assign(a, {[k]:v}) // if it is not an array, merge into resultant object
return a;
}, {});
console.log(d);
You could take a recursive approach.
const
fn = o => Object.assign(...Object.entries(o).map(([k, v]) => Array.isArray(v) ? Object.assign(...v.map(fn)) : { [k]: v })),
d = { Coupon_Code: "code", Coupon_Name: "namie", Coupon_Desc: 1000, selectedCity: [{ Coupon_City_Name: "xyz" }], selectedCategory: [{ Coupon_Category_Name: "Shopping" }], selectedCompany: [{ Coupon_Company_Name: "Shopper Stop" }], selectedState: [{ Coupon_State_Name: "abc" }], Coupon_Date: "2222-02-22" },
result = fn(d);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
A possible iterative solution is:
function flatten(obj) {
let r = {}
for (let [key, value] of Object.entries(obj)) {
if (Array.isArray(value)) {
Object.assign(r, value[0]);
} else {
Object.assign(r, {[key]: value});
}
}
return r;
}
Something like this:
const d = { Coupon_Code: "code", Coupon_Name: "namie", Coupon_Desc: 1000, selectedCity: [{ Coupon_City_Name: "xyz" }], selectedCategory: [{ Coupon_Category_Name: "Shopping" }], selectedCompany: [{ Coupon_Company_Name: "Shopper Stop" }], selectedState: [{ Coupon_State_Name: "abc" }], Coupon_Date: "2222-02-22" };
function toSingleObj(obj) {
var result = {};
Object.entries(obj).forEach(([key,value]) => {
if (Array.isArray(value)) {
Object.entries(value[0]).forEach(([k,v]) => {
result[k] = v;
});
} else {
result[key] = value;
}
});
return result;
}
console.log("Result: ", toSingleObj(d));

make combinations of two array in json

Input :
"options": [
{
"name": "Color",
"values": [
"Blue",
"Black"
]
},
{
"name": "Size",
"values": [
"Small",
"Large"
]
}
]
Output: "variants": [
{
"option1": "Blue",
"option2": "Small"
},
{
"option1": "Blue",
"option2": "Large"
},
{
"option1": "Black",
"option2": "Small"
},
{
"option1": "Black",
"option2": "Large"
}
]
How to solve this using recursion ?The options array can contain multiple name and i need the above out to be displayed. Can it be done using cartesian product i guess
You could take an iterative and recursive approach for getting all option combinations.
function getCombinations(array) {
function iter(i, temp) {
if (i === array.length) {
result.push(temp.reduce(function (o, v, i) {
o['option' + (i + 1)] = v;
return o;
}, {}));
return;
}
array[i].values.forEach(function (a) {
iter(i + 1, temp.concat(a));
});
}
var result = [];
iter(0, []);
return result;
}
var options = [{ name: "Color", values: ["Blue", "Black"] }, { name: "Size", values: ["155", "159"] }, { name: 'Material', values: ['Sand', 'Clay', 'Mud'] }],
variants = getCombinations(options);
console.log(variants);
.as-console-wrapper { max-height: 100% !important; top: 0; }
ES6
function getCombinations(array) {
function iter(i, temp) {
if (i === array.length) {
result.push(temp);
return;
}
array[i].values.forEach(a => iter(i + 1, Object.assign({}, temp, { ['option' + (i + 1)]: a })));
}
var result = [];
iter(0, {});
return result;
}
var options = [{ name: "Color", values: ["Blue", "Black"] }, { name: "Size", values: ["155", "159"] }, { name: 'Material', values: ['Sand', 'Clay', 'Mud'] }],
variants = getCombinations(options);
console.log(variants);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can use nested Array.map() calls, create the objects, and flatten the sub arrays using Array.concat():
const options = [{"name":"Color","values":["Blue","Black"]},{"name":"Size","values":["155","159"]}]
const [{ values: colors }, { values: sizes }] = options
const result = [].concat(...colors.map((option1) => sizes.map((option2) => ({
option1,
option2
}))))
console.log(result)
var myarray = {"options": [
{
"name": "Color",
"values": [
"Blue",
"Black"
]
},
{
"name": "Size",
"values": [
"155",
"159"
]
}
]};
const key = myarray.options[0].values;
const value =myarray.options[1].values;
const output = _.zipWith(key, value, (key, value)=> ({ key, value }));
console.log(output);
<script src="https://cdn.jsdelivr.net/lodash/4.16.6/lodash.min.js"></script>

Print array of objects entire path

Good Day People
I have an array of objects and I need to print out the path of each node value and last print key and value for special (by name) node.
This is the array of objects or JSON
[{
"Name": "2007",
"Elements": [{
"Name": "country1",
"Elements": [{
"House": "house1",
"water": 1.8
}],
"Data": {}
},
{
"Name": "country2",
"Elements": [{
"Name": "city2",
"Elements": [{
"Name": "neighbourhood2",
"Elements": [{
"House": "house2",
"water": 2.8
}]
}],
"Data": {}
}],
"Data": {}
},
{
"Name": "country3",
"Elements": [{
"House": "house2",
"uni bill": 3.8
}],
"Data": {}
}
],
"Data": {}
}]
The output should be like this
2007 > country1 > house > water: 1.8
2007 > city2 > neighbourhood2 > house2 > electricity: 2.8
2007 > country3 > house > uni bill: 3.8
++++++++++++++ edited +++++++++++++++
function objectToPaths(data) {
var validId = /^[a-z_$][a-z0-9_$]*$/i;
var result = [];
doIt(data, "");
return result;
function doIt(data, s) {
if (data && typeof data === "object") {
if (Array.isArray(data)) {
for (var i = 0; i < data.length; i++) {
doIt(data[i], s + "");
}
} else {
for (var p in data) {
if (validId.test(p)) {
doIt(data[p], s + " > " + data[p]);
} else {
doIt(data[p], s + "");
}
}
}
} else {
result.push(s);
}
}
}
this is a rewrite of a function I found here but I did not get the expected result
+++++++++++++++++++++++ end of the edit +++++++++++++++++++++++
Please help
Thanks in advance
What you are looking for is a Depth First Traversal function that recursively print properties:
function print(arr, path) { // print takes an array an an accumulated path from which it will start printing
arr.forEach(function(obj) { // for each object obj in the array
if(obj.Elements) { // if the object obj has sub elements in it
print(obj.Elements, path + " > " + obj.Name); // then call print on those elements, providin the absolute path to this object
} else { // otherwise (it is a leaf)
const bills = Object.keys(obj)
.filter(key => key !== "House")
.map(key => `${key}: ${obj[key]}`)
.join(', ')
console.log(path.slice(3) + " > " + obj.House + " > " + bills); // print the accumulated path along with the House property of this object (removing the first 3 letters from path which are equal to " > ")
}
});
};
var arr = [{"Name":"2007","Elements":[{"Name":"country1","Elements":[{"House":"house1","water":1.8}],"Data":{}},{"Name":"country2","Elements":[{"Name":"city2","Elements":[{"Name":"neighbourhood2","Elements":[{"House":"house2","water":2.8}]}],"Data":{}}],"Data":{}},{"Name":"country3","Elements":[{"House":"house2","uni bill":3.8}],"Data":{}}],"Data":{}}];
print(arr, "");
You could take a function for iterating and collect the path to the last object.
function iter(array, path) {
path = path || [];
array.forEach(function (o) {
if (o.Elements) {
return iter(o.Elements, path.concat(o.Name));
}
Object.keys(o).forEach(function (k) {
if (k !== 'House') {
console.log(path.concat(o.House, k).join(' > ') + ': ' + o[k]);
}
});
});
}
var data = [{ Name: "2007", Elements: [{ Name: "country1", Elements: [{ House: "house1", water: 1.8 }], Data: {} }, { Name: "country2", Elements: [{ Name: "city2", Elements: [{ Name: "neighbourhood2", Elements: [{ House: "house2", water: 2.8 }] }], Data: {} }], Data: {} }, { Name: "country3", Elements: [{ House: "house2", "uni bill": 3.8 }], Data: {} }], Data: {} }];
iter(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Traverse JSON object to build JSTree

I have a JSON object and want to traverse it so that it matches the structure of JSTree:
Original JSON:
{
"analogBasebandProcessorBoardType": "Test_BOARD",
"tuners": {
"tuner1": "RFE_MAIN",
"tuner2": "MAX93"
},
"allowedSoftConfigs": ["30-16", "30-29", "10-22"]
}
It should look like this:
{
'core': {
'data': [
{
'text': 'analogBasebandProcessorBoardType',
'children':
[
{
'text': 'Test_BOARD'
}
]
},
{
'text': 'tuners',
'children':
[{
'text': 'Tuner1',
'children':
[{
'text': 'RFE_MAIN'
}]
},
{
'text': 'Tuner2',
'children':
[{
'text': 'MAX93'
}]
}
]
},
{
'text': 'allowedSoftConfigs',
'children':
[
{
'text': '30-16'
},
{
'text': '30-29'
},
{
'text': '10-22'
}
]
},
]
}
}
I think the only way to solve this is traversing. I have tried it but it is not exactly what I want, but I think I am not very far away from the solution.
This is the JSON that is being generated:
{
"core": {
"data": {
"analogBasebandProcessorBoardType": {
"text": "analogBasebandProcessorBoardType",
"children": [{
"text": "Test_BOARD"
}],
"tuners": {
"tuner1": {
"text": "tuner1",
"children": [{
"text": "RFE_MAIN"
}],
"tuner2": {
"text": "tuner2",
"children": [{
"text": "MAX93"
}],
"allowedSoftConfigs": {
"0": {
"1": {
"2": {
"text": "2",
"children": [{
"text": "10-22"
}]
},
"text": "1",
"children": [{
"text": "30-29"
}]
},
"text": "0",
"children": [{
"text": "30-16"
}]
}
}
}
}
}
}
}
}
}
My code alway uses the "name" as the key for the data-array. It would be correct if there is no key. But I am not sure where this behavior is caused.
It would be great if someone could take a look on it as I don't know how to solve it.
Here is the complete code but it is easier to view in jsfiddle i think:
//function to add something to objects with a string path
function assign(obj, prop, value) {
if (typeof prop === "string")
prop = prop.split(".");
if (prop.length > 1) {
var e = prop.shift();
assign(obj[e] =
Object.prototype.toString.call(obj[e]) === "[object Object]"
? obj[e]
: {},
prop,
value);
} else
obj[prop[0]] = value;
}
$(function() {
// 6 create an instance when the DOM is ready
var tbjsonstring = '{ "analogBasebandProcessorBoardType": "Test_BOARD", "tuners": { "tuner1": "RFE_MAIN","tuner2": "MAX93" }, "allowedSoftConfigs": ["30-16", "30-29", "10-22"]}';
var tbjson = JSON.parse(tbjsonstring);
var computedJSON = {
'core': {
'data': [
]
}
}
var path = "core.data";
console.log(tbjson);
(function traverse(o) {
var z = 0;
for (var i in o) {
data0 = {
'text': i,
}
data1 = {
'text': o[i],
}
if(traversed == 1){
console.log("traversed" + o[i]);
// assign(computedJSON,path,data1);
traversed = 0;
}else{
// assign(computedJSON,path,data0);
}
console.log('key : ' + i + ', value: ' + o[i]);
//console.log(path);
path = path+"."+i;
z++;
if (o[i] !== null && typeof(o[i])=="object") {
//going on step down in the object tree!!
var traversed = "1";
traverse(o[i]);
}else{
//key value pair, no children
data = {};
data = {
'text': i,
'children': [{
'text': o[i]
}]
}
assign(computedJSON,path,data);
}
}
})
(tbjson);
//print to the console
console.log(JSON.stringify(computedJSON));
//This is the working json, computedJSON should looke like this:
var jstreejson = {
'core': {
'data': [
{
'text': 'analogBasebandProcessorBoardType',
'children':
[
{
'text': 'Test_BOARD'
}
]
},
{
'text': 'tuners',
'children':
[{
'text': 'Tuner1',
'children':
[{
'text': 'RFE_MAIN'
}]
},
{
'text': 'Tuner2',
'children':
[{
'text': 'MAX93'
}]
}
]
},
{
'text': 'allowedSoftConfigs',
'children':
[
{
'text': '30-16'
},
{
'text': '30-29'
},
{
'text': '10-22'
}
]
},
]
}
}
//jstree initialization
$('#jstree').jstree(jstreejson);
$('#tbjstree').jstree(computedJSON);
// 7 bind to events triggered on the tree
$('#jstree').on("changed.jstree", function(e, data) {
console.log(data.selected);
});
});
The won't run in the stackoverflow-snippet-editor (even with loaded js/css files) so please visit jsfiddle for a working demo:
<a href='https://jsfiddle.net/dnffx4g8/6/' target='_blank'>JSFiddle Demo</a>
jsfiddle-link: https://jsfiddle.net/dnffx4g8/6/
You could use an iterative an recursive approach for it, with a function who checks for array and object and iterates accordingly.
function buildObject(source) {
if (Array.isArray(source)) {
return source.reduce(function (r, a) {
if (a !== null && typeof a === 'object') {
return r.concat(buildObject(a));
}
r.push({ text: a });
return r;
}, []);
}
if (source !== null && typeof source === 'object') {
return Object.keys(source).map(function (k) {
return {
text: k,
children: buildObject(source[k])
};
});
}
return [{ text: source }];
}
var data = { "analogBasebandProcessorBoardType": "Test_BOARD", "tuners": { "tuner1": "RFE_MAIN", "tuner2": "MAX93" }, "allowedSoftConfigs": ["30-16", "30-29", "10-22"], "PathValue": [{ "links": ["in1->GSES_1.in1", "GSES_1.out1->GSES_1.in1", "GSES_1.out1->out1_1"], "ParamFile": "IN1_OUT12.txt" }, { "links": ["in1->GSES_1.in1", "GSES_1.out2->GSES_2.in1", "GSES_2.out1->out1_2"], "ParamFile": "IN1_OUT52.txt" }] },
result = { core: { data: buildObject(data) } };
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
ES6
function buildObject(source) {
if (Array.isArray(source)) {
return source.map(text => ({ text }));
}
if (source !== null && typeof source === 'object') {
return Object.keys(source).map(text => ({ text, children: buildObject(source[text])}));
}
return [{ text: source }];
}
var object = { analogBasebandProcessorBoardType: "Test_BOARD", tuners: { tuner1: "RFE_MAIN", tuner2: "MAX93" }, allowedSoftConfigs: ["30-16", "30-29", "10-22"] },
result = { core: { data: buildObject(object) } };
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Given an object named data, you could use this ES6 function:
var result = {
core: {
data: (function treeify(data) {
return Array.isArray(data) ? data.map ( value => treeify(value) )
: typeof data !== 'object' || data == null ? { text: data }
: Object.keys(data).map(key => ({ text:key, children: [treeify(data[key])] }));
})(data)
}
};
Here is a snippet with your sample data:
var data = {
"analogBasebandProcessorBoardType": "Test_BOARD",
"tuners": {
"tuner1": "RFE_MAIN",
"tuner2": "MAX93"
},
"allowedSoftConfigs": ["30-16", "30-29", "10-22"]
};
var result = {
core: {
data: (function treeify(data) {
return Array.isArray(data) ? data.map ( value => treeify(value) )
: typeof data !== 'object' || data == null ? { text: data }
: Object.keys(data).map ( key => ({ text: key, children: [treeify(data[key])] }) );
})(data)
}
};
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
NB: I would not name your objects tbjson or computedJson, to avoid confusion with plain JavaScript objects. The term JSON is better reserved for the text notation.
Explanation of the Code
treeify is a recursive function. The value it returns depends on the data type of the argument that is passed to it:
When it is an array (Array.isArray()) then the function is called recursively for each element (treeify(value)), and these results are assembled in a new array (the return value of data.map()) that is returned to the caller.
When it is a non-object (as null is considered an object a separate test is needed for that), then the value is given to the text property of a new object which is returned to the caller ({ text: data }).
When it is an object, the keys of that object are iterated (Object.keys(data).map()) and for each corresponding value the function is called recursively (treeify(data[key])). That result is put in an array and assigned to the children property of a new object, while the key is assigned to the text property of that same object. This is returned to the caller.
The result variable will start the calling chain for initialising the value of the data property.

Categories

Resources