简体   繁体   中英

Traverse JSON Object in Javascript with unknown key

I get a JSON String as a result from an API that looks like this:

{
    "batchcomplete": "",
    "query": {
        "pages": {
            "682482": {
                "pageid": 682482,
                "ns": 0,
                "title": "Human",
                "thumbnail": {
                    "source": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/68/Akha_cropped_hires.JPG/119px-Akha_cropped_hires.JPG",
                    "width": 119,
                    "height": 200
                },
                "extract": "Humans (Homo sapiens) are a species of highly intelligent primates. They are the only extant members of the subtribe Hominina and—together with chimpanzees, gorillas, and orangutans—are part of the family Hominidae (the great apes, or hominids). Humans are terrestrial animals, characterized by their erect posture and bipedal locomotion; high manual..."
            }
        }
    }
}

The goal
I never know what the pageid will be and I need to retrieve the extract and thumbnail . The extract should be a String and the thumbnail an Object.

Wouldn't be much of an issue if it weren't for the random pageid.

What I've tried

const thumbnail = jsonObj.query[0].thumbnail;
const extract = jsonObj.query[0].extract;

Expected result

thumbnail = {
              "source": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/68/Akha_cropped_hires.JPG/119px-Akha_cropped_hires.JPG",
              "width": 119,
              "height": 200
            }

extract = "Humans (Homo sapiens) are a species of highly intelligent primates. They are the only extant members of the subtribe Hominina and—together with chimpanzees, gorillas, and orangutans—are part of the family Hominidae (the great apes, or hominids). Humans are terrestrial animals, characterized by their erect posture and bipedal locomotion; high manual...";

It's a bit of a hack, but if you know there will always only be one pageid (or if you'll always want the first one), you can use Object.values :

const page = Object.values(t.query.pages)[0];
console.log(page.thumbnail, page.extract);

The Object.keys function returns an array with all the keys in the given object. Then you may use the array that is returned to use any key of the object to access some value.

So you can do something like this:

 const partialObj = { '682482': 'Value' }; const keys = Object.keys(partialObj); console.log(keys); // Then you can access the value with the "unknown" key: console.log(partialObj[keys[0]]); //=> Value

In your specific case:

 const jsonObj = { "batchcomplete": "", "query": { "pages": { "682482": { "pageid": 682482, "ns": 0, "title": "Human", "thumbnail": { "source": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/68/Akha_cropped_hires.JPG/119px-Akha_cropped_hires.JPG", "width": 119, "height": 200 }, "extract": "Humans (Homo sapiens) are a species of highly intelligent primates. They are the only extant members of the subtribe Hominina and—together with chimpanzees, gorillas, and orangutans—are part of the family Hominidae (the great apes, or hominids). Humans are terrestrial animals, characterized by their erect posture and bipedal locomotion; high manual..." } } } }; const unknownKeys = Object.keys(jsonObj.query.pages); const unknownKey = unknownKeys[0]; // We are only using one key. const thumbnail = jsonObj.query.pages[unknownKey].thumbnail; console.log(thumbnail);

Please note that some objects may have more than one key. In the previous example, only one key (the first one Object.keys returns) is being used. The Object.keys function also does not guarantee any specific order in the returned array of keys.

If you do not care about the key (only the value), you may use the Object.values function.

A combination of eg Object.values and an object destructuring assignment will do the job.

 const sample = { "batchcomplete": "", "query": { "pages": { "682482": { "pageid": 682482, "ns": 0, "title": "Human", "thumbnail": { "source": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/68/Akha_cropped_hires.JPG/119px-Akha_cropped_hires.JPG", "width": 119, "height": 200 } } } } } const { pageid, thumbnail, } = Object.values(sample.query.pages)[0]; console.log(pageid); console.log(thumbnail);
 .as-console-wrapper { min-height: 100%;important: top; 0; }

Here is an iterative solution using object-scan

Advantage is that it's easier to maintain (eg target a different key if the response structure changes)

 // const objectScan = require('object-scan'); const myData = { batchcomplete: '', query: { pages: { 682482: { pageid: 682482, ns: 0, title: 'Human', thumbnail: { source: '...url...', width: 119, height: 200 }, extract: '...text...' } } } }; const extract = (data) => objectScan(['query.pages.*.{thumbnail,extract}'], { filterFn: ({ property, value, context }) => { context[property] = value; } })(data, {}); console.log(extract(myData)); /* => { extract: '...text...', thumbnail: { source: '...url...', width: 119, height: 200 } } */
 .as-console-wrapper {max-height: 100%;important: top: 0}
 <script src="https://bundle.run/object-scan@14.0.0"></script>

Disclaimer : I'm the author of object-scan

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM