Vous trouverez ci-dessous un objet JSON que je reçois en réponse. Quelques remarques:

  • C'est juste une partie de l'objet
  • L'objet n'a pas les mêmes clés pour toutes les sociétés

JSON:

{
    "company": {
        "result": [
            {
                "profile": {
                    "address": "One Microsoft Way",
                    "bosses": [
                        {
                            "name": "Mr. Satya  Nadella",
                            "age": 53,
                            "totalPay": {
                                "raw": 13603180,
                                "fmt": "13.6M",
                                "longFmt": "13,603,180"
                            }
                        },
                        {
                            "name": "Mr. Bradford L. Smith",
                            "age": 61,
                            "title": "Pres & Chief Legal Officer",
                            "totalPay": {
                                "raw": 4265576,
                                "fmt": "4.27M",
                                "longFmt": "4,265,576"
                            }
                        }
                    ],
                    "auditRisk": 1,
                },
                "statistics": {
                    "enterpriseValue": {
                        "raw": 1570244395008,
                        "fmt": "1.57T",
                    },
                    "profitMargins": {
                        "raw": 0.32285
                    },
                    "financialCurrency": "USD"
                }
            }
        ],
        "error": null
    }
}

J'aimerais:

  • vérifier un certain nombre de chemins dans cet objet
  • si le chemin pointe vers une valeur de chaîne, renvoie la valeur si elle existe
  • si le chemin pointe vers un tableau, parcourez le tableau pour retourner le chemin de chaque élément du tableau
  • si un élément spécifique est nommé dans le chemin, ne renvoie que celui-là
  • il doit y avoir une gestion correcte des erreurs

Scénario

var json = JSON.parse(response.getContentText());

var paths = arr[
    "profile/address",                 <-- return the value
    "profile/sector",                  <-- does not exist, return false
    "profile/bosses/name",             <-- is an array with 2 elements, return both names
    "profile/bosses/1/age"             <-- only return age of second element
    "statistics/enterpriseValue/fmt",  <-- return the value
    "profitMargins/fmt",               <-- does not exist, return false
]

Production attendue:

One Microsoft Way
false
Mr. Satya Nadella
Mr. Bradford L. Smith
53
false

J'ai essayé pendant un certain temps maintenant, mais je suis confus. Peux-tu m'aider?

for (path in paths) {
    var steps = path.split('/')
    
    for (step in steps) {
        if (step.hasOwnProperty(steps[step+1])) {
            if (typeof path[step] === "object") {
                // array, so loop again?
            }
            if (typeof path[step] === undefined) {
                // value doesn't exist?
                
                return false;
            }
            if (typeof path[step] !== undefined) {
                return path[step].value;
            }
        }
    }
}
1
Pr0no 13 janv. 2021 à 23:42

3 réponses

Meilleure réponse

Je pense qu'il y a certaines choses à considérer en premier, donc je ne commence à chercher l'objet que dans le chemin suivant

getPath( data, 'company/result/0' )

Ce qui me permet de commencer beaucoup plus facilement à rechercher les chemins spécifiés.

Je pense que la syntaxe que vous choisissez pour les propriétés n'est peut-être pas la plus simple, car il est un peu plus difficile de décider de rechercher dans tous les éléments ou simplement dans un seul élément du tableau (par exemple, vous recherchez quelque chose comme {{X0 }} d'un élément).

Des sous-tableaux existent toujours dans ce résultat, mais vous pouvez aplatir les résultats si vous le souhaitez.

const data = {
    "company": {
        "result": [
            {
                "profile": {
                    "address": "One Microsoft Way",
                    "bosses": [
                        {
                            "name": "Mr. Satya  Nadella",
                            "age": 53,
                            "totalPay": {
                                "raw": 13603180,
                                "fmt": "13.6M",
                                "longFmt": "13,603,180"
                            }
                        },
                        {
                            "name": "Mr. Bradford L. Smith",
                            "age": 61,
                            "title": "Pres & Chief Legal Officer",
                            "totalPay": {
                                "raw": 4265576,
                                "fmt": "4.27M",
                                "longFmt": "4,265,576"
                            }
                        }
                    ],
                    "auditRisk": 1,
                },
                "statistics": {
                    "enterpriseValue": {
                        "raw": 1570244395008,
                        "fmt": "1.57T",
                    },
                    "profitMargins": {
                        "raw": 0.32285
                    },
                    "financialCurrency": "USD"
                }
            }
        ],
        "error": null
    }
};

const pathsToFind = [
  "profile/address",
  "profile/sector",                 
  "profile/bosses/name",            
  "profile/bosses/1/age",            
  "statistics/enterpriseValue/fmt",
  "profitMargins/fmt"
];



function getPath( obj, path ) {
  if (!path || !obj) {
    return null;
  }
  const [currentPath, ...rest] = path.split('/');
  const nextPath = rest.join('/');
  const currentObj = obj[currentPath];
  
  // final path, exit here
  if (nextPath.length === 0) {
    return currentObj;
  }
  
  if (Array.isArray( currentObj )) {
    // does an element exit at the next level
    if ( currentObj[nextPath[0]] ) {
      // will continue reading for 1 element
      return getPath( currentObj, nextPath );
    }
    // return all the subpaths, skip the ones that are falsy
    return currentObj.map( item => getPath( item, nextPath ) ).filter( v => v );
  }
  // get the next part of the object
  return getPath( currentObj, nextPath );
}

function getMatchingValues( obj, paths ) {
  return paths.flatMap( path => getPath( obj, path ) ?? false );
}

console.log( getMatchingValues( getPath( data, 'company/result/0' ), pathsToFind ) );
1
Icepickle 13 janv. 2021 à 23:57

Il existe plusieurs solutions de contournement pour votre solution, mais je pense que vous pourriez considérer la solution JSONPath comme un moyen standard d'interroger votre objet JSON.

Consultez ce npm JSONPath Guide.

0
Soroosh Kh 13 janv. 2021 à 20:52

Solution

let data = {
  profile: {
    address: "One Microsoft Way",
    bosses: [
      {
        name: "Mr. Satya  Nadella",
        age: 53,
        totalPay: {
          raw: 13603180,
          fmt: "13.6M",
          longFmt: "13,603,180",
        },
      },
      {
        name: "Mr. Bradford L. Smith",
        age: 61,
        title: "Pres & Chief Legal Officer",
        totalPay: {
          raw: 4265576,
          fmt: "4.27M",
          longFmt: "4,265,576",
        },
      },
    ],
    auditRisk: 1,
  },
  statistics: {
    enterpriseValue: {
      raw: 1570244395008,
      fmt: "1.57T",
    },
    profitMargins: {
      raw: 0.32285,
    },
    financialCurrency: "USD",
  },
};

let paths = [
  "profile/address",
  "profile/sector",
  "profile/bosses/name",
  "profile/bosses/1/age",
  "statistics/enterpriseValue/fmt",
  "profitMargins/fmt",
];

let GenratedResult = paths
  .map((p) => p.split("/"))
  .reduce((allResults, c) => {
    let curRes = c.reduce((innerResults, innerCur) => {
      if (typeof innerResults === "object" && innerResults.length) {
        if (!isNaN(innerCur * 1)) {
          return innerResults[innerCur] || false;
        } else {
          let R = innerResults
            .map((v) => v[innerCur] || false)
            .filter((i) => i);
          return R.length ? R : false;
        }
      }

      return innerResults && innerResults[innerCur]
        ? innerResults[innerCur]
        : false;
    }, data);

    return [...allResults, curRes];
  }, [])
  .flatMap((i) => i);

console.log(GenratedResult);
0
MUHAMMAD ILYAS 13 janv. 2021 à 21:51
65709489