skip to Main Content
[
   {
      "id":"0001",
      "type":"donut",
      "name":"Cake",
      "ppu":0.55,
      "batters":{
         "batter":[
            {
               "id":"1001",
               "type":"Regular"
            },
            {
               "id":"1002",
               "type":"Chocolate"
            }
         ]
      },
      "topping":[
         {
            "id":"5002",
            "type":"Glazed"
         }
         {
            "id":"5004",
            "type":"Maple"
         }
      ]
   },
   {
      "id":"0002",
      "type":"donut",
      "name":"Raised",
      "ppu":0.55,
      "batters":{
         "batter":[
            {
               "id":"1001",
               "type":"Regular"
            }
         ]
      },
      "topping":[
         {
            "id":"5003",
            "type":"Chocolate"
         },
         {
            "id":"5004",
            "type":"Maple"
         }
      ]
   },
   {
      "id":"0003",
      "type":"donut",
      "name":"Old Fashioned",
      "ppu":0.55,
      "batters":{
         "batter":[
            {
               "id":"1001",
               "type":"Regular"
            },
            {
               "id":"1002",
               "type":"Chocolate"
            }
         ]
      },
      "topping":[
         {
            "id":"5001",
            "type":"None"
         },
         {
            "id":"5004",
            "type":"Maple"
         }
      ]
   }
]

Expected output: [donut, Regular, Chocolate, Glazed, Maple, donut, Regular, Chocolate, Maple, donut, Regular, Chocolate, None, Maple]

Get all values of key(type) from above JSon into an array, including all children. Attached is the sample json and also expected output.
Is there any _lodash function for this or any Javascript function is also fine.

5

Answers


  1. Try this:

    JSON.stringify([{"id":"0001","type":"donut","name":"Cake","ppu":0.55,"batters":{"batter":[{"id":"1001","type":"Regular"},{"id":"1002","type":"Chocolate"}]},"topping":[{"id":"5002","type":"Glazed"},{"id":"5004","type":"Maple"}]},{"id":"0002","type":"donut","name":"Raised","ppu":0.55,"batters":{"batter":[{"id":"1001","type":"Regular"}]},"topping":[{"id":"5003","type":"Chocolate"},{"id":"5004","type":"Maple"}]},{"id":"0003","type":"donut","name":"Old Fashioned","ppu":0.55,"batters":{"batter":[{"id":"1001","type":"Regular"},{"id":"1002","type":"Chocolate"}]},"topping":[{"id":"5001","type":"None"},{"id":"5004","type":"Maple"}]}]).match(/(?<=["']type["']:s*["'])(w+)/g)
    

    BTW, your json object is not in a correct format.

    "topping":[
         {
            "id":"5002",
            "type":"Glazed"
         }
         {
            "id":"5004",
            "type":"Maple"
         }
      ]
    

    There should be a comma between 5002 and 5004.

    Login or Signup to reply.
  2. Try This:

    1. Include Lodash via a CDN in your HTML file
    2. he getAllValuesByKey function is defined to recursively search for the key type and collect its values.
     const data = [
             {
                "id": "0001",
                "type": "donut",
                "name": "Cake",
                "ppu": 0.55,
                "batters": {
                   "batter": [
                      {
                         "id": "1001",
                         "type": "Regular"
                      },
                      {
                         "id": "1002",
                         "type": "Chocolate"
                      }
                   ]
                },
                "topping": [
                   {
                      "id": "5002",
                      "type": "Glazed"
                   },
                   {
                      "id": "5004",
                      "type": "Maple"
                   }
                ]
             },
             {
                "id": "0002",
                "type": "donut",
                "name": "Raised",
                "ppu": 0.55,
                "batters": {
                   "batter": [
                      {
                         "id": "1001",
                         "type": "Regular"
                      }
                   ]
                },
                "topping": [
                   {
                      "id": "5003",
                      "type": "Chocolate"
                   },
                   {
                      "id": "5004",
                      "type": "Maple"
                   }
                ]
             },
             {
                "id": "0003",
                "type": "donut",
                "name": "Old Fashioned",
                "ppu": 0.55,
                "batters": {
                   "batter": [
                      {
                         "id": "1001",
                         "type": "Regular"
                      },
                      {
                         "id": "1002",
                         "type": "Chocolate"
                      }
                   ]
                },
                "topping": [
                   {
                      "id": "5001",
                      "type": "None"
                   },
                   {
                      "id": "5004",
                      "type": "Maple"
                   }
                ]
             }
          ];
    
          function getAllValuesByKey(obj, key) {
             const result = [];
             function recursiveSearch(obj) {
                if (_.isObject(obj)) {
                   _.forOwn(obj, (value, k) => {
                      if (k === key) {
                         result.push(value);
                      }
                      recursiveSearch(value);
                   });
                } else if (_.isArray(obj)) {
                   obj.forEach(item => recursiveSearch(item));
                }
             }
             recursiveSearch(obj);
             return result;
          }
    
          const types = getAllValuesByKey(data, 'type');
          console.log(types); 
    <html lang="en">
    <head>
       <meta charset="UTF-8">
       <meta name="viewport" content="width=device-width, initial-scale=1.0">
       <title>Extract JSON Values</title>
       <script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>
    </head>
    <body>
    </body>
    </html>
    Login or Signup to reply.
  3. This is a nice candidate for writing a generator function (and recursion):

    function* valuesForKey(data, key) {
        if (Object(data) !== data) return; // It's not an object
        if (Object.hasOwn(data, key)) yield data[key];
        for (const child of Object.values(data)) yield* valuesForKey(child, key);
    }
    
    const data = [{"id":"0001","type":"donut","name":"Cake","ppu":0.55,"batters":{"batter":[{"id":"1001","type":"Regular"},{"id":"1002","type":"Chocolate"}]},"topping":[{"id":"5002","type":"Glazed"},{"id":"5004","type":"Maple"}]},{"id":"0002","type":"donut","name":"Raised","ppu":0.55,"batters":{"batter":[{"id":"1001","type":"Regular"}]},"topping":[{"id":"5003","type":"Chocolate"},{"id":"5004","type":"Maple"}]},{"id":"0003","type":"donut","name":"Old Fashioned","ppu":0.55,"batters":{"batter":[{"id":"1001","type":"Regular"},{"id":"1002","type":"Chocolate"}]},"topping":[{"id":"5001","type":"None"},{"id":"5004","type":"Maple"}]}];
    const keys = [...valuesForKey(data, "type")];
    console.log(keys);
    Login or Signup to reply.
  4. I think you need a recursive function for extract all values by key.

    • Be careful with large JSONs and memory.
    function extractValuesByKey(obj, field) {
      if (!obj) return [];
      if (typeof obj !== "object") return [];
      if (Array.isArray(obj))
        return obj.map((value) => extractValuesByKey(value, field)).flat();
    
      let result = [];
      Object.keys(obj).forEach((key) => {
        if (key === field) result.push(obj[key]);
        else result = result.concat(extractValuesByKey(obj[key], field));
      });
      return result;
    }
    
    Login or Signup to reply.
  5. There are prebuilt functions in lodash libaray you can use them. Here is the code for the same.

    const allTypes = _.flatMap(jsonArray, (obj) => [
        obj.type,
        ..._.flatMap(obj.batters.batter, (obj) => [obj.type]),
        ..._.flatMap(obj.topping, (obj) => [obj.type]),
    ]);

    I have used flatmap inside flatmap to maintain the ordering of the output.

    if you don’t want to mainatin the order you can use concat function provided by the lodash library.

    const allTypes = _.concat(
        _.map(jsonArray, 'type'),
        _.map(_.flatMap(jsonArray, 'batters.batter'), 'type'),
        _.map(_.flatMap(jsonArray, 'topping'), 'type')
    );

    You can you javascript method to get the desired output.

        const types = [];
        
        jsonArray.forEach(item => {
            // Extract "type" from the current object
            if (item.type) {
                types.push(item.type);
            }
    
            // Recursively extract "type" from nested "batter" array
            if (item.batters && item.batters.batter) {
                item.batters.batter.forEach(batter => {
                    if (batter.type) {
                        types.push(batter.type);
                    }
                });
            }
    
            // Recursively extract "type" from nested "topping" array
            if (item.topping) {
                item.topping.forEach(topping => {
                    if (topping.type) {
                        types.push(topping.type);
                    }
                });
            }
        });

    here jsonArray is your input.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search