Я хотел бы пересечь дерево объектов JSON, но не могу найти для этого никакой библиотеки. Это не кажется трудным, но кажется, что он изобретает колесо.
В XML есть так много руководств, показывающих, как перемещаться по дереву XML с помощью DOM: (
Я хотел бы пересечь дерево объектов JSON, но не могу найти для этого никакой библиотеки. Это не кажется трудным, но кажется, что он изобретает колесо.
В XML есть так много руководств, показывающих, как перемещаться по дереву XML с помощью DOM: (
Если вы считаете, что 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);
Объект 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 для таких вещей, поскольку они значительно облегчают написание такого кода.
function traverse(o ) {
for (i in o) {
if (!!o[i] && typeof(o[i])=="object") {
console.log(i, o[i])
traverse(o[i] );
}
}
}
Там есть новая библиотека для перемещения данных JSON с JavaScript, которая поддерживает множество различных случаев использования.
https://npmjs.org/package/traverse
https://github.com/substack/js-traverse
Он работает со всеми видами объектов JavaScript. Он даже обнаруживает циклы.
Он также предоставляет путь для каждого node.
Зависит от того, что вы хотите сделать. Здесь приведен пример перемещения дерева объектов 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
Если вы просматриваете фактическую строку 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)
})
РЕДАКТИРОВАТЬ: все приведенные ниже примеры в этом ответе были отредактированы, чтобы включить новую переменную пути, полученную из итератора в соответствии с @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"]));
Я хотел использовать идеальное решение @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);
Большинство движков 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)
Мой 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"]
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>
Лучшим решением для меня было следующее:
простой и без использования каких-либо фреймворков
var doSomethingForAll = function (arg) {
if (arg != undefined && arg.length > 0) {
arg.map(function (item) {
// do something for item
doSomethingForAll (item.subitem)
});
}
}
Вы можете получить все ключи/значения и сохранить иерархию с помощью этого
// 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/...)
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>);
}
Я создал библиотеку для перемещения и редактирования глубоко вложенных объектов 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'}