2017-10-18 14 views
0

Je crée une API où les valeurs sont transmises par le serveur via un attribut de données, afin que le JS puisse récupérer des informations ... Mon JS fait un AJAX appeler et un objet JSON est retourné ...JavaScript: Convertir une chaîne et la concaténer pour créer dynamiquement une référence de propriété d'objet

{ 
    "data": { 
     "results": { 
      "type": [ 
       { 
        "cars" : { 
         "brands": { 
          "ford" : {}, 
          "honda" : {} 
         } 
        } 
       } 
      ] 
     } 
    } 
} 

afin d'obtenir la marque, je viens de taper

let brand = data.result.type[0].cars.brands.ford 

cette façon, je peux obtenir les résultats dont j'ai besoin, mais je dois construire cette chemin dynamiquement, en joignant 2 partiels du chemin. Comme je l'ai dit au début de la question, certaines informations sont transmises via l'attribut de données et l'info est type[0].cars.brands.ford ... J'ai besoin de joindre ceci à data.result dans mon code. Je suis actuellement être en mesure d'obtenir le résultat souhaité en utilisant eval(), comme si

entry.querySelectorAll('[data-brand]').forEach((e) => 
    let brand = eval('data.result.' + e.dataset.brand); 
) 

Je sais que beaucoup d'entre vous diront que l'utilisation eval() est mauvais et je suis très au courant, mais je ne pouvais pas trouver un meilleur moyen de faire cela et il y a un autre problème, quand la marque, disons, nissan n'est pas sur le JSON, j'obtiens une erreur TypeError: Cannot read property 'nissan' of undefined ... On pourrait éviter cela, en vérifiant si la propriété existe, avant continuer le code, mais je ne sais pas comment faire ce genre de test lorsque eval() est impliqué.

... Alors au fond, ce que je dois, est une meilleure façon de construire dynamiquement le chemin de la propriété, qui peut être testé pour voir si la propriété existe ...

Merci à l'avance ...

+1

Vous pouvez utiliser data.result [ 'property_name'] – Danmoreng

+0

Merci pour la réponse, mais j'ai déjà essayé et cela n'a pas fonctionné ... –

+0

Qu'est-ce qui ne fonctionne pas exactement? – Danmoreng

Répondre

0
const brand = e.dataset.brand.split(".").reduce((obj,id) => obj[id] || {}, data.results); 

Ce doenst supports, donc faire:

type.0.whatever.keys 

Pour revenir non défini pour les clés non existants (au lieu d'un objet vide):

const brand = e.dataset.brand.split(".").reduce((obj,id) => (obj || {})[id], data.results); 
+0

merci beaucoup beaucoup ... je n'ai pas connaître le 'réduire()' ... J'étudierai plus à ce sujet ... Cela a fonctionné parfaitement .. Je juste ai dû ajuster les attributs de données, pour tourner 'type [0] .cars.brands.ford' à 'type.0.cars.brands.ford' –

+0

@paulo youre bienvenue;) –

+0

juste une question ... Je vais encore obtenir TypeError: Impossible de lire la propriété 'sentra' de undefined' parce que la marque «Nissan» n'était pas définie ... donc, fondamentalement cela n'existe pas 'type.0.cars.brands.nissan.sentra' ... comment arrêter l'itération' reduce() ', quand une propriété parent n'existe pas? Voudrais-tu savoir? –

-1

Vous pouvez vérifier la méthode lodash get qui vous permet d'accéder aux valeurs de l'objet en utilisant path.

Si lodash est trop grand pour vous, il suffit de revoir leur implémentation.

+0

Merci pour l'aide, mais je crois que lodash est grand pour mes besoins ... –

0

Vous pouvez vérifier si les données. résultat a la propriété d'abord, et ensuite seulement faire votre marque variable:

if(data.result.hasOwnProperty(e.dataset.brand)){ 
    let brand = data.result[e.dataset.brand]; 
} 
+0

J'ai déjà essayé ça, mais ça ne marche pas ... J'obtiens 'undefined' comme résultat ... –

+0

Cela arrive si' data.result' n'a aucune des marques que vous bouclez. – Danmoreng

0

Vous pouvez String#match trouver toutes les clés, puis itérer les touches à l'aide Array#reduce, et obtenir la valeur de clé de l'objet:

const obj = {"data":{"results":{"type":[{"cars":{"brands":{"ford":{"name":"ford"},"honda":{"name":"honda"}}}}]}}}; 
 

 
const brand = 'data.results.type[0].cars.brands.ford'; 
 

 
const getPathValue = (src, path) => path.match(/[^.\[\]]+/g) 
 
    .reduce((p, k) => typeof p === 'object' ? p[k] : p, src); 
 

 
const brandOBj = getPathValue(obj, brand); 
 

 
console.log(brandOBj);