Chciałbym przejść przez drzewo obiektów JSON, ale nie mogę znaleźć do tego żadnej biblioteki. Nie wydaje się to trudne, ale wydaje się, że trzeba na nowo wynaleźć koło.
W XML jest tak wiele samouczków pokazujących, jak przejść przez drzewo XML z DOM :(
javascript
json
Patsy Issa
źródło
źródło
Odpowiedzi:
Jeśli uważasz, że jQuery to przesada jak na tak prymitywne zadanie, możesz zrobić coś takiego:
źródło
this
wartość w funkcji docelowej, podczas gdyo
powinien to być pierwszy parametr funkcji. Ustawienie go nathis
(która byłabytraverse
funkcją) jest jednak trochę dziwne, ale i tak nie jest tak, żeprocess
używathis
odwołania. Równie dobrze mógł być zerowy./*jshint validthis: true */
powyższego,func.apply(this,[i,o[i]]);
aby uniknąć błęduW040: Possible strict violation.
spowodowanego użyciemthis
traverse
funkcji, która śledzi głębokość. Wywołanie Wenn rekurencyjnie dodaje 1 do bieżącego poziomu.Obiekt JSON to po prostu obiekt JavaScript. To właśnie oznacza JSON: JavaScript Object Notation. Tak więc przechodziłbyś przez obiekt JSON, ale ogólnie wybrałbyś „przechodzenie” przez obiekt JavaScript.
W ES2017 zrobiłbyś:
Zawsze możesz napisać funkcję, która rekurencyjnie zejdzie do obiektu:
To powinien być dobry punkt wyjścia. Gorąco polecam używanie do tego celu nowoczesnych metod javascript, ponieważ znacznie ułatwiają pisanie takiego kodu.
źródło
function traverse(jsonObj) { if(jsonObj && typeof jsonObj == "object" ) { ...
źródło
much better
?!!o[i] && typeof o[i] == 'object'
Jest nowa biblioteka do przechodzenia przez dane JSON za pomocą JavaScript, która obsługuje wiele różnych przypadków użycia.
https://npmjs.org/package/traverse
https://github.com/substack/js-traverse
Działa ze wszystkimi rodzajami obiektów JavaScript. Wykrywa nawet cykle.
Zapewnia również ścieżkę do każdego węzła.
źródło
Zależy od tego, co chcesz zrobić. Oto przykład przechodzenia przez drzewo obiektów JavaScript, wypisywania kluczy i wartości na bieżąco:
źródło
Jeśli przechodzisz przez rzeczywisty ciąg JSON , możesz użyć funkcji ożywiania.
Podczas przechodzenia przez obiekt:
źródło
EDYCJA : Wszystkie poniższe przykłady w tej odpowiedzi zostały zmodyfikowane tak, aby zawierały nową zmienną ścieżki uzyskaną z iteratora zgodnie z żądaniem @ supersan . Zmienna ścieżki jest tablicą ciągów, w której każdy ciąg w tablicy reprezentuje każdy klucz, do którego uzyskano dostęp do wynikowej iterowanej wartości z oryginalnego obiektu źródłowego. Zmienna ścieżki może być wprowadzona do funkcji / metody get lodash . Lub możesz napisać własną wersję get lodash, która obsługuje tylko takie tablice:
EDYTOWAĆ : ta zmieniona odpowiedź rozwiązuje nieskończone pętle przechodzenia.
Zatrzymywanie nieznośnego przechodzenia przez nieskończone obiekty
Ta zredagowana odpowiedź nadal zapewnia jedną z dodatkowych zalet mojej oryginalnej odpowiedzi, która pozwala na użycie dostarczonej funkcji generatora w celu użycia czystszego i prostego iterowalnego interfejsu (pomyśl o użyciu
for of
pętli tak, jak wfor(var a of b)
przypadku, gdyb
jest iterowalny ia
jest elementem iterowalnym ). Używając funkcji generatora, będąc prostszym interfejsem API, pomaga również w ponownym użyciu kodu, dzięki czemu nie musisz powtarzać logiki iteracji wszędzie tam, gdzie chcesz głęboko iterować właściwości obiektu, a także umożliwiabreak
wyjście z pętla, jeśli chcesz wcześniej przerwać iterację.Zauważyłem, że jedna rzecz, która nie została poruszona i której nie ma w mojej pierwotnej odpowiedzi, to ostrożność podczas przechodzenia przez dowolne (tj. Dowolny "losowy" zestaw) obiektów, ponieważ obiekty JavaScript mogą odwoływać się do siebie. Stwarza to możliwość nieskończonej pętli przechodzenia. Niezmodyfikowane dane JSON nie mogą jednak odwoływać się do siebie, więc jeśli używasz tego szczególnego podzbioru obiektów JS, nie musisz się martwić o nieskończone pętle przechodzenia i możesz odwołać się do mojej oryginalnej odpowiedzi lub innych odpowiedzi. Oto przykład niekończącego się przejścia (pamiętaj, że nie jest to fragment kodu, który można uruchomić, ponieważ w przeciwnym razie spowodowałoby to awarię karty przeglądarki).
Również w obiekcie generatora w moim edytowanym przykładzie zdecydowałem się użyć,
Object.keys
zamiastfor in
którego iteruje tylko klucze nieprototypowe na obiekcie. Możesz to zmienić samodzielnie, jeśli chcesz, aby zawierały klucze prototypowe. Zobacz moją oryginalną sekcję odpowiedzi poniżej dla obu implementacji zObject.keys
ifor in
.Gorzej - spowoduje to nieskończoną pętlę na obiektach odnoszących się do samych siebie:
Aby się przed tym uchronić, możesz dodać zestaw w zamknięciu, tak aby przy pierwszym wywołaniu funkcji zaczęła budować pamięć obiektów, które widziała i nie kontynuowała iteracji, gdy napotka już widziany obiekt. Poniższy fragment kodu robi to, a zatem obsługuje nieskończone przypadki zapętlenia.
Lepiej - to nie będzie nieskończonej pętli na obiektach odwołujących się do siebie:
Oryginalna odpowiedź
Aby uzyskać nowszy sposób, możesz to zrobić, jeśli nie masz nic przeciwko porzuceniu IE i głównie obsłudze nowszych przeglądarek (sprawdź tabelę es6 kangax pod kątem kompatybilności). Możesz użyć do tego generatorów es2015 . Odpowiednio zaktualizowałem odpowiedź @ TheHippo. Oczywiście, jeśli naprawdę chcesz obsługiwać IE, możesz użyć transpilera JavaScript babel .
Jeśli chcesz mieć tylko własne wyliczalne właściwości (w zasadzie nie-prototypowe właściwości łańcucha), możesz zmienić to na iterację przy użyciu
Object.keys
ifor...of
zamiast tego pętli:źródło
Chciałem wykorzystać idealne rozwiązanie @TheHippo w funkcji anonimowej, bez użycia funkcji procesu i wyzwalacza. Poniższe działania zadziałały dla mnie, udostępnianie dla początkujących programistów, takich jak ja.
źródło
Większość silników JavaScript nie optymalizuje rekurencji ogonowej (może to nie stanowić problemu, jeśli twój JSON nie jest głęboko zagnieżdżony), ale zwykle błądzę po stronie ostrożności i zamiast tego wykonuję iterację, np.
źródło
Mój skrypt:
Wejście JSON:
Wywołanie funkcji:
Wyjście zgodnie z moją potrzebą:
źródło
źródło
Najlepszym rozwiązaniem dla mnie było:
proste i bez użycia jakichkolwiek ram
źródło
Dzięki temu możesz uzyskać wszystkie klucze / wartości i zachować hierarchię
To jest modyfikacja na ( https://stackoverflow.com/a/25063574/1484447 )
źródło
źródło
Stworzyłem bibliotekę do przechodzenia i edycji głęboko zagnieżdżonych obiektów JS. Sprawdź API tutaj: https://github.com/dominik791
Możesz także interaktywnie bawić się biblioteką za pomocą aplikacji demo: https://dominik791.github.io/obj-traverse-demo/
Przykłady użycia: Zawsze powinieneś mieć obiekt root, który jest pierwszym parametrem każdej metody:
Drugim parametrem jest zawsze nazwa właściwości przechowującej zagnieżdżone obiekty. W powyższym przypadku tak byłoby
'children'
.Trzeci parametr to obiekt, którego używasz do znajdowania obiektu / obiektów, które chcesz znaleźć / zmodyfikować / usunąć. Na przykład, jeśli szukasz obiektu o identyfikatorze równym 1,
{ id: 1}
jako trzeci parametr podasz .Możesz:
findFirst(rootObj, 'children', { id: 1 })
znaleźć pierwszy obiekt za pomocąid === 1
findAll(rootObj, 'children', { id: 1 })
aby znaleźć wszystkie obiekty za pomocąid === 1
findAndDeleteFirst(rootObj, 'children', { id: 1 })
aby usunąć pierwszy pasujący obiektfindAndDeleteAll(rootObj, 'children', { id: 1 })
aby usunąć wszystkie pasujące obiektyreplacementObj
jest używany jako ostatni parametr w dwóch ostatnich metodach:findAndModifyFirst(rootObj, 'children', { id: 1 }, { id: 2, name: 'newObj'})
aby zmienić pierwszy znaleziony obiekt za pomocąid === 1
na{ id: 2, name: 'newObj'}
findAndModifyAll(rootObj, 'children', { id: 1 }, { id: 2, name: 'newObj'})
zmienić wszystkie obiekty za pomocąid === 1
na{ id: 2, name: 'newObj'}
źródło