Gostaria de percorrer uma árvore de objetos JSON, mas não consigo encontrar nenhuma biblioteca para isso. Não parece difícil, mas parece reinventar a roda.
No XML, existem muitos tutoriais mostrando como percorrer uma árvore XML com o DOM :(
javascript
json
Patsy Issa
fonte
fonte
Respostas:
Se você acha que o jQuery é um exagero para uma tarefa tão primitiva, você pode fazer algo assim:
fonte
this
valor na função de destino, enquanto queo
deve ser o primeiro parâmetro para a função. Configurá-lo parathis
(qual seria atraverse
função) é um pouco estranho, mas não é como seprocess
usasse athis
referência de qualquer maneira. Poderia muito bem ter sido nulo./*jshint validthis: true */
acimafunc.apply(this,[i,o[i]]);
para evitar o erroW040: Possible strict violation.
causado pelo uso dethis
traverse
função que rastreia a profundidade. Quando chamarmos recursivamente, adicione 1 ao nível atual.Um objeto JSON é simplesmente um objeto Javascript. Na verdade, é isso que JSON significa: JavaScript Object Notation. Portanto, você atravessaria um objeto JSON, no entanto, escolheria "atravessar" um objeto Javascript em geral.
No ES2017, você faria:
Você sempre pode escrever uma função para descer recursivamente ao objeto:
Este deve ser um bom ponto de partida. Eu recomendo o uso de métodos javascript modernos para essas coisas, pois eles facilitam a escrita desse código.
fonte
function traverse(jsonObj) { if(jsonObj && typeof jsonObj == "object" ) { ...
fonte
much better
?!!o[i] && typeof o[i] == 'object'
Há uma nova biblioteca para atravessar dados JSON com JavaScript que suporta muitos casos de uso diferentes.
https://npmjs.org/package/traverse
https://github.com/substack/js-traverse
Funciona com todos os tipos de objetos JavaScript. Ele até detecta ciclos.
Ele fornece o caminho de cada nó também.
fonte
Depende do que você quer fazer. Aqui está um exemplo de como percorrer uma árvore de objetos JavaScript, imprimir chaves e valores conforme segue:
fonte
Se você estiver atravessando uma string JSON real , poderá usar uma função reviver.
Ao atravessar um objeto:
fonte
EDIT : Todos os exemplos abaixo nesta resposta foram editados para incluir uma nova variável de caminho produzida pelo iterador conforme a solicitação do @ supersan . A variável path é uma matriz de cadeias em que cada cadeia na matriz representa cada chave acessada para obter o valor iterado resultante do objeto de origem original. A variável path pode ser inserida na função / método get do lodash . Ou você pode escrever sua própria versão do get do lodash, que lida apenas com matrizes da seguinte forma:
EDIT : Esta resposta editada resolve percursos de loop infinito.
Parando travessias de objetos infinitos traquinas
Esta resposta editada ainda fornece um dos benefícios adicionais da minha resposta original, que permite que você use a função de gerador fornecida para usar uma interface iterável mais limpa e simples (pense em usar
for of
loops comofor(var a of b)
ondeb
é um iterável ea
é um elemento do iterável ) Usando a função de gerador além de ser uma API simples que também ajuda com a reutilização de código, tornando-a assim que você não tem que repetir a lógica iteração em todos os lugares que você quer iterate profundamente sobre as propriedades do objeto e também torna possívelbreak
fora do o loop se você gostaria de interromper a iteração anteriormente.Uma coisa que noto que não foi abordada e que não está na minha resposta original é que você deve ter cuidado ao atravessar objetos arbitrários (ou seja, qualquer conjunto "aleatório" de)), porque os objetos JavaScript podem ser auto-referenciados. Isso cria a oportunidade de ter percursos de loop infinitos. Dados JSON não modificados, no entanto, não podem ser auto-referenciados; portanto, se você estiver usando esse subconjunto específico de objetos JS, não precisará se preocupar com percursos de loop infinito e poderá consultar minha resposta original ou outras respostas. Aqui está um exemplo de uma travessia sem fim (observe que não é um trecho de código executável, porque, caso contrário, poderia travar a guia do navegador).
Também no objeto gerador no meu exemplo editado, optei por usar, em
Object.keys
vez defor in
iterar apenas chaves não protótipo no objeto. Você pode trocar isso sozinho se quiser incluir as chaves do protótipo. Veja minha seção de resposta original abaixo para ambas as implementações comObject.keys
efor in
.Pior - Isso fará um loop infinito em objetos auto-referenciais:
Para se salvar disso, você pode adicionar um conjunto em um fechamento, para que, quando a função for chamada pela primeira vez, comece a criar uma memória dos objetos que viu e não continue a iteração depois de encontrar um objeto já visto. O trecho de código abaixo faz isso e, portanto, lida com casos de loop infinito.
Melhor - Isso não fará um loop infinito em objetos auto-referenciais:
Resposta original
Para uma maneira mais nova de fazer isso, se você não se importa em deixar o IE e principalmente oferecer suporte a navegadores mais atuais (verifique a tabela es6 da kangax para compatibilidade). Você pode usar os geradores es2015 para isso. Atualizei a resposta do @ TheHippo de acordo. Obviamente, se você realmente deseja suporte ao IE, pode usar o transpiler babel JavaScript.
Se você deseja apenas propriedades enumeráveis (basicamente propriedades de cadeia que não são protótipos), é possível alterá-lo para iterar usando
Object.keys
umfor...of
loop:fonte
Eu queria usar a solução perfeita do @TheHippo em uma função anônima, sem o uso de funções de processo e gatilho. O seguinte funcionou para mim, compartilhando para programadores iniciantes como eu.
fonte
A maioria dos mecanismos Javascript não otimiza a recursão da cauda (isso pode não ser um problema se o seu JSON não estiver profundamente aninhado), mas eu geralmente erro por precaução e faço a iteração, por exemplo
fonte
Meu script:
JSON de entrada:
Chamada de função:
Saída conforme minha necessidade:
fonte
fonte
A melhor solução para mim foi a seguinte:
simples e sem usar nenhuma estrutura
fonte
Você pode obter todas as chaves / valores e preservar a hierarquia com este
Esta é uma modificação em ( https://stackoverflow.com/a/25063574/1484447 )
fonte
fonte
Eu criei uma biblioteca para percorrer e editar objetos JS aninhados profundos. Confira a API aqui: https://github.com/dominik791
Você também pode brincar com a biblioteca interativamente usando o aplicativo demo: https://dominik791.github.io/obj-traverse-demo/
Exemplos de uso: você sempre deve ter um objeto raiz, que é o primeiro parâmetro de cada método:
O segundo parâmetro é sempre o nome da propriedade que contém objetos aninhados. No caso acima, seria
'children'
.O terceiro parâmetro é um objeto que você usa para encontrar objetos que deseja localizar / modificar / excluir. Por exemplo, se você estiver procurando por objetos com um ID igual a 1, passará
{ id: 1}
como o terceiro parâmetro.E você pode:
findFirst(rootObj, 'children', { id: 1 })
para encontrar o primeiro objeto comid === 1
findAll(rootObj, 'children', { id: 1 })
para encontrar todos os objetos comid === 1
findAndDeleteFirst(rootObj, 'children', { id: 1 })
excluir o primeiro objeto correspondentefindAndDeleteAll(rootObj, 'children', { id: 1 })
excluir todos os objetos correspondentesreplacementObj
é usado como o último parâmetro em dois últimos métodos:findAndModifyFirst(rootObj, 'children', { id: 1 }, { id: 2, name: 'newObj'})
para alterar o primeiro objeto encontrado comid === 1
para o{ id: 2, name: 'newObj'}
findAndModifyAll(rootObj, 'children', { id: 1 }, { id: 2, name: 'newObj'})
para alterar todos os objetos comid === 1
para o{ id: 2, name: 'newObj'}
fonte