Пройдите все узлы дерева объектов JSON с помощью JavaScript
Я хотел бы пересечь дерево объектов JSON, но не могу найти для этого никакой библиотеки. Это не кажется трудным, но кажется, что он изобретает колесо.
В XML есть так много руководств, показывающих, как перемещаться по дереву XML с помощью DOM: (
Ответы
Ответ 1
Если вы считаете, что jQuery является overkill для такой примитивной задачи, вы можете сделать что-то вроде этого:
//your object
var o = {
foo:"bar",
arr:[1,2,3],
subo: {
foo2:"bar2"
}
};
//called with every property and its value
function process(key,value) {
console.log(key + " : "+value);
}
function traverse(o,func) {
for (var i in o) {
func.apply(this,[i,o[i]]);
if (o[i] !== null && typeof(o[i])=="object") {
//going one step down in the object tree!!
traverse(o[i],func);
}
}
}
//that all... no magic, no bloated framework
traverse(o,process);
Ответ 2
Объект JSON - это просто объект Javascript. Вот что на самом деле означает JSON: JavaScript Object Notation. Таким образом, вы будете проходить через объект JSON, но в целом вы будете выбирать "обходить" объект Javascript.
В ES2017 вы бы сделали:
Object.entries(jsonObj).forEach(([key, value]) => {
// do something with key and val
});
Вы всегда можете написать функцию, чтобы рекурсивно спускаться в объект:
function traverse(jsonObj) {
if( jsonObj !== null && typeof jsonObj == "object" ) {
Object.entries(jsonObj).forEach(([key, value]) => {
// key is either an array index or object key
traverse(value);
});
}
else {
// jsonObj is a number or string
}
}
Это должно быть хорошей отправной точкой. Я настоятельно рекомендую использовать современные методы javascript для таких вещей, поскольку они значительно облегчают написание такого кода.
Ответ 3
function traverse(o ) {
for (i in o) {
if (!!o[i] && typeof(o[i])=="object") {
console.log(i, o[i])
traverse(o[i] );
}
}
}
Ответ 4
Там есть новая библиотека для перемещения данных JSON с JavaScript, которая поддерживает множество различных случаев использования.
https://npmjs.org/package/traverse
https://github.com/substack/js-traverse
Он работает со всеми видами объектов JavaScript. Он даже обнаруживает циклы.
Он также предоставляет путь для каждого node.
Ответ 5
Зависит от того, что вы хотите сделать. Здесь приведен пример перемещения дерева объектов JavaScript, печати ключей и значений по мере их появления:
function js_traverse(o) {
var type = typeof o
if (type == "object") {
for (var key in o) {
print("key: ", key)
js_traverse(o[key])
}
} else {
print(o)
}
}
js> foobar = {foo: "bar", baz: "quux", zot: [1, 2, 3, {some: "hash"}]}
[object Object]
js> js_traverse(foobar)
key: foo
bar
key: baz
quux
key: zot
key: 0
1
key: 1
2
key: 2
3
key: 3
key: some
hash
Ответ 6
Если вы просматриваете фактическую строку JSON, вы можете использовать функцию reviver.
function traverse (json, callback) {
JSON.parse(json, function (key, value) {
if (key !== '') {
callback.call(this, key, value)
}
return value
})
}
traverse('{"a":{"b":{"c":{"d":1}},"e":{"f":2}}}', function (key, value) {
console.log(arguments)
})
При перемещении объекта:
function traverse (obj, callback, trail) {
trail = trail || []
Object.keys(obj).forEach(function (key) {
var value = obj[key]
if (Object.getPrototypeOf(value) === Object.prototype) {
traverse(value, callback, trail.concat(key))
} else {
callback.call(obj, key, value, trail)
}
})
}
traverse({a: {b: {c: {d: 1}}, e: {f: 2}}}, function (key, value, trail) {
console.log(arguments)
})
Ответ 7
РЕДАКТИРОВАТЬ: все приведенные ниже примеры в этом ответе были отредактированы, чтобы включить новую переменную пути, полученную из итератора в соответствии с @supersan request. Переменная path - это массив строк, где каждая строка в массиве представляет каждый ключ, к которому был получен доступ, чтобы получить результирующее повторяющееся значение из исходного исходного объекта. Переменная пути может быть передана в функцию/метод lodash get. Или вы можете написать свою собственную версию lodash get, которая обрабатывает только массивы примерно так:
function get (object, path) {
return path.reduce((obj, pathItem) => obj ? obj[pathItem] : undefined, object);
}
const example = {a: [1,2,3], b: 4, c: { d: ["foo"] }};
// these paths exist on the object
console.log(get(example, ["a", "0"]));
console.log(get(example, ["c", "d", "0"]));
console.log(get(example, ["b"]));
// these paths do not exist on the object
console.log(get(example, ["e", "f", "g"]));
console.log(get(example, ["b", "f", "g"]));
Ответ 8
Я хотел использовать идеальное решение @TheHippo в анонимной функции без использования функций процесса и триггера. Следующие работали для меня, как для меня, так и для начинающих программистов.
(function traverse(o) {
for (var i in o) {
console.log('key : ' + i + ', value: ' + o[i]);
if (o[i] !== null && typeof(o[i])=="object") {
//going on step down in the object tree!!
traverse(o[i]);
}
}
})
(json);
Ответ 9
Большинство движков Javascript не оптимизируют хвостовую рекурсию (это может быть не проблема, если ваш JSON не глубоко вложен), но я обычно ошибаюсь на стороне осторожности и вместо этого выполняю итерацию, например.
function traverse(o, fn) {
const stack = [o]
while (stack.length) {
const obj = stack.shift()
Object.keys(obj).forEach((key) => {
fn(key, obj[key], obj)
if (obj[key] instanceof Object) {
stack.unshift(obj[key])
return
}
})
}
}
const o = {
name: 'Max',
legal: false,
other: {
name: 'Maxwell',
nested: {
legal: true
}
}
}
const fx = (key, value, obj) => console.log(key, value)
traverse(o, fx)
Ответ 10
Мой Script:
op_needed = [];
callback_func = function(val) {
var i, j, len;
results = [];
for (j = 0, len = val.length; j < len; j++) {
i = val[j];
if (i['children'].length !== 0) {
call_func(i['children']);
} else {
op_needed.push(i['rel_path']);
}
}
return op_needed;
};
Вход JSON:
[
{
"id": null,
"name": "output",
"asset_type_assoc": [],
"rel_path": "output",
"children": [
{
"id": null,
"name": "output",
"asset_type_assoc": [],
"rel_path": "output/f1",
"children": [
{
"id": null,
"name": "v#",
"asset_type_assoc": [],
"rel_path": "output/f1/ver",
"children": []
}
]
}
]
}
]
Вызов функции:
callback_func(inp_json);
Выход по моей потребности:
["output/f1/ver"]
Ответ 11
var test = {
depth00: {
depth10: 'string'
, depth11: 11
, depth12: {
depth20:'string'
, depth21:21
}
, depth13: [
{
depth22:'2201'
, depth23:'2301'
}
, {
depth22:'2202'
, depth23:'2302'
}
]
}
,depth01: {
depth10: 'string'
, depth11: 11
, depth12: {
depth20:'string'
, depth21:21
}
, depth13: [
{
depth22:'2201'
, depth23:'2301'
}
, {
depth22:'2202'
, depth23:'2302'
}
]
}
, depth02: 'string'
, dpeth03: 3
};
function traverse(result, obj, preKey) {
if(!obj) return [];
if (typeof obj == 'object') {
for(var key in obj) {
traverse(result, obj[key], (preKey || '') + (preKey ? '[' + key + ']' : key))
}
} else {
result.push({
key: (preKey || '')
, val: obj
});
}
return result;
}
document.getElementById('textarea').value = JSON.stringify(traverse([], test), null, 2);
<textarea style="width:100%;height:600px;" id="textarea"></textarea>
Ответ 12
Лучшим решением для меня было следующее:
простой и без использования каких-либо фреймворков
var doSomethingForAll = function (arg) {
if (arg != undefined && arg.length > 0) {
arg.map(function (item) {
// do something for item
doSomethingForAll (item.subitem)
});
}
}
Ответ 13
Вы можете получить все ключи/значения и сохранить иерархию с помощью этого
// get keys of an object or array
function getkeys(z){
var out=[];
for(var i in z){out.push(i)};
return out;
}
// print all inside an object
function allInternalObjs(data, name) {
name = name || 'data';
return getkeys(data).reduce(function(olist, k){
var v = data[k];
if(typeof v === 'object') { olist.push.apply(olist, allInternalObjs(v, name + '.' + k)); }
else { olist.push(name + '.' + k + ' = ' + v); }
return olist;
}, []);
}
// run with this
allInternalObjs({'a':[{'b':'c'},{'d':{'e':5}}],'f':{'g':'h'}}, 'ob')
Это модификация (fooobar.com/questions/49508/...)
Ответ 14
var localdata = [{''}]// Your json array
for (var j = 0; j < localdata.length; j++)
{$(localdata).each(function(index,item)
{
$('#tbl').append('<tr><td>' + item.FirstName +'</td></tr>);
}
Ответ 15
Я создал библиотеку для перемещения и редактирования глубоко вложенных объектов JS. Ознакомьтесь с API здесь: https://github.com/dominik791
Вы также можете играть в библиотеке интерактивно с помощью демонстрационного приложения:
https://dominik791.github.io/obj-traverse-demo/
Примеры использования:
Вы всегда должны иметь корневой объект, который является первым параметром каждого метода:
var rootObj = {
name: 'rootObject',
children: [
{
'name': 'child1',
children: [ ... ]
},
{
'name': 'child2',
children: [ ... ]
}
]
};
Второй параметр всегда является именем свойства, которое содержит вложенные объекты. В приведенном выше случае это будет 'children'
.
Третий параметр - это объект, который вы используете для поиска объектов/объектов, которые вы хотите найти/изменить/удалить. Например, если вы ищете объект с id равным 1, то вы передадите { id: 1}
в качестве третьего параметра.
И вы можете:
-
findFirst(rootObj, 'children', { id: 1 })
, чтобы найти первый объект с id === 1
-
findAll(rootObj, 'children', { id: 1 })
, чтобы найти все объекты с id === 1
-
findAndDeleteFirst(rootObj, 'children', { id: 1 })
для удаления первого объекта соответствия
-
findAndDeleteAll(rootObj, 'children', { id: 1 })
для удаления всех соответствующих объектов
replacementObj
используется как последний параметр в двух последних методах:
-
findAndModifyFirst(rootObj, 'children', { id: 1 }, { id: 2, name: 'newObj'})
изменить первый найденный объект с помощью id === 1
на { id: 2, name: 'newObj'}
-
findAndModifyAll(rootObj, 'children', { id: 1 }, { id: 2, name: 'newObj'})
, чтобы изменить все объекты с помощью id === 1
на { id: 2, name: 'newObj'}