简体   繁体   English

遍历JSON对象以构建JSTree

[英]Traverse JSON object to build JSTree

I have a JSON object and want to traverse it so that it matches the structure of JSTree: 我有一个JSON对象,想遍历它,使其与JSTree的结构匹配:

Original JSON: 原始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: 这是正在生成的JSON:

 { "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: 这是完整的代码,但是我认为在jsfiddle中更容易查看:

 //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/ 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 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: 给定一个名为data的对象,您可以使用以下ES6函数:

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. 注:我不会命名对象tbjsoncomputedJson,以避免与普通的JavaScript对象混淆。 The term JSON is better reserved for the text notation. 术语JSON最好保留给文本表示法。

Explanation of the Code 代码说明

treeify is a recursive function. treeify是一个递归函数。 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. 当它是一个数组( Array.isArray() )时,将为每个元素( treeify(value) )递归调用该函数,并将这些结果组装在一个新数组中( data.map()的返回值),即返回给呼叫者。

  • 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 } ). 如果它是一个非对象(因为将null视为一个对象,则需要对其进行单独的测试),则将该值赋予新对象的text属性,该属性将返回给调用者( { 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]) ). 当它是一个对象时,将迭代该对象的键( Object.keys(data).map() ),并为每个对应的值递归调用该函数( 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. 将该结果放入数组中并分配给新对象的children属性,而将键分配给同一对象的text属性。 This is returned to the caller. 这将返回给调用方。

The result variable will start the calling chain for initialising the value of the data property. 结果变量将启动调用链以初始化data属性的值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM