简体   繁体   中英

Retrieving data from JSON object with similar keys

I have JSON data that is returned from a AJAX GET request. This request returns different sets of meals and how to make them including the ingredients needed and their measurements. Snippet of JSON data (Some key : value have been removed for easier viewing):

{
  "idMeal":"52768",
  "strMeal":"Apple Frangipan Tart",
  "strDrinkAlternate":null,
  "strCategory":"Dessert",
  "strIngredient1":"digestive biscuits",
  "strIngredient2":"butter",
  "strIngredient3":"Bramley apples",
  "strIngredient4":"butter, softened",
  "strIngredient5":"caster sugar",
  "strIngredient6":"free-range eggs, beaten",
  "strIngredient7":"ground almonds",
  "strIngredient8":"almond extract",
  "strIngredient9":"flaked almonds",
  "strIngredient10":"",
  "strIngredient11":"",
  "strIngredient12":"",
  "strIngredient13":"",
  "strIngredient14":"",
  "strIngredient15":"",
  "strIngredient16":null,
  "strIngredient17":null,
  "strIngredient18":null,
  "strIngredient19":null,
  "strIngredient20":null,
  "strMeasure1":"175g\/6oz",
  "strMeasure2":"75g\/3oz",
  "strMeasure3":"200g\/7oz",
  "strMeasure4":"75g\/3oz",
  "strMeasure5":"75g\/3oz",
  "strMeasure6":"2",
  "strMeasure7":"75g\/3oz",
  "strMeasure8":"1 tsp",
  "strMeasure9":"50g\/1\u00beoz",
  "strMeasure10":"",
  "strMeasure11":"",
  "strMeasure12":"",
  "strMeasure13":"",
  "strMeasure14":"",
  "strMeasure15":"",
  "strMeasure16":null,
  "strMeasure17":null,
  "strMeasure18":null,
  "strMeasure19":null,
  "strMeasure20":null
},
{
  "idMeal":"52893",
  "strMeal":"Apple & Blackberry Crumble",
  "strDrinkAlternate":null,
  "strCategory":"Dessert",
  "strIngredient1":"Plain Flour",
  "strIngredient2":"Caster Sugar",
  "strIngredient3":"Butter",
  "strIngredient4":"Braeburn Apples",
  "strIngredient5":"Butter",
  "strIngredient6":"Demerara Sugar",
  "strIngredient7":"Blackberrys",
  "strIngredient8":"Cinnamon",
  "strIngredient9":"Ice Cream",
  "strIngredient10":"",
  "strIngredient11":"",
  "strIngredient12":"",
  "strIngredient13":"",
  "strIngredient14":"",
  "strIngredient15":"",
  "strIngredient16":"",
  "strIngredient17":"",
  "strIngredient18":"",
  "strIngredient19":"",
  "strIngredient20":"",
  "strMeasure1":"120g",
  "strMeasure2":"60g",
  "strMeasure3":"60g",
  "strMeasure4":"300g",
  "strMeasure5":"30g",
  "strMeasure6":"30g",
  "strMeasure7":"120g",
  "strMeasure8":"\u00bc teaspoon",
  "strMeasure9":"to serve",
  "strMeasure10":"",
  "strMeasure11":"",
  "strMeasure12":"",
  "strMeasure13":"",
  "strMeasure14":"",
  "strMeasure15":"",
  "strMeasure16":"",
  "strMeasure17":"",
  "strMeasure18":"",
  "strMeasure19":"",
  "strMeasure20":""
}

JAVASCRIPT/JQUERY CODE

$.each($(response), function(key, val) {
      let mealName = val.strMeal;
      let mealCategory = val.strCategory;
      let mealInstructions = val.strInstructions;
      let mealIngredient1 = val.strIngredient1;
      let mealIngredient2 = val.strIngredient2;
      ... // Variables continued
      ...
      let mealIngredient20 = val.strIngredient20;

      let mealMeasure1 = val.strMeasure1;
      let mealMeasure2 = val.strMeasure2;
      ... // Variables continued
      ...
      let mealMeasure20 = val.strMeasure20;

      console.log(mealName);
      console.log(mealCategory);
      console.log(mealInstructions);
      console.log(mealIngredient1);
      console.log(mealIngredient2);
      console.log(mealMeasure1);
      console.log(mealMeasure2);
    });

As you can see, each meal can have up to 20 ingredients and measurements and will differ from one another. So, my question is whether there is a better or more efficient way in getting each ingredient and measurement than my method of retrieving each and storing in an individual variable, while also getting rid of null or empty variables that won't be used?

Check out Object.entries() and map :

 const data = { "idMeal":"52768", "strMeal":"Apple Frangipan Tart", "strDrinkAlternate":null, "strCategory":"Dessert", "strIngredient1":"digestive biscuits", "strIngredient2":"butter", "strIngredient3":"Bramley apples", "strIngredient4":"butter, softened", "strIngredient5":"caster sugar", "strIngredient6":"free-range eggs, beaten", "strIngredient7":"ground almonds", "strIngredient8":"almond extract", "strIngredient9":"flaked almonds", "strIngredient10":"", "strIngredient11":"", "strIngredient12":"", "strIngredient13":"", } // get an array of [key, value] entries from the response const properties = Object.entries(data); // filter out the items whose value is empty const nonEmpty = properties.filter(([_, value]) => value); // do whatever you need to do with the rest nonEmpty.map(([name, value]) => console.log(`${name}: ${value}`));

The code above can be tightened up by chaining the filter and map operations:

Object.entries(data)
  .filter(([_, value]) => value )
  .map(([key, value]) => console.log( key, value ));

You can also extract and/or filter non-ingredient properties separately if that's useful:

 const data = { "idMeal": "52768", "strMeal": "Apple Frangipan Tart", "strDrinkAlternate": null, "strCategory": "Dessert", "strIngredient1": "digestive biscuits", "strIngredient2": "butter", "strIngredient3": "Bramley apples", "strIngredient4": "butter, softened", "strIngredient5": "caster sugar", "strIngredient6": "free-range eggs, beaten", "strIngredient7": "ground almonds", "strIngredient8": "almond extract", "strIngredient9": "flaked almonds", "strIngredient10": "", "strIngredient11": "", "strIngredient12": "", "strIngredient13": "", } // extract a few known properties, and capture the rest in the 'others' variable. const {idMeal, strMeal, ...others} = data; Object.entries(others) .filter(([_, value]) => value) // no empty values .filter(([key]) => key.includes('Ingredient')) // only 'ingredient' items .map(([key, value]) => console.log(key, value));

Your strIngredient# object properties should be an array strIngredient[] which you can iterate over dynamicly, likewise with strMeasure[]. As your code is written now you are setting a lot of properties that are uneccessary depending on the given recepie.

You can use object destructuring and use rest operator to get the remaining parts.

 const data = { "idMeal":"52768", "strMeal":"Apple Frangipan Tart", "strDrinkAlternate":null, "strCategory":"Dessert", "strIngredient1":"digestive biscuits", "strIngredient2":"butter", "strIngredient3":"Bramley apples", "strIngredient4":"butter, softened", "strIngredient5":"caster sugar", "strIngredient6":"free-range eggs, beaten", "strIngredient7":"ground almonds", "strIngredient8":"almond extract", "strIngredient9":"flaked almonds", "strIngredient10":"", "strIngredient11":"", "strIngredient12":"", "strIngredient13":"", "strIngredient14":"", "strIngredient15":"", "strIngredient16":null, "strIngredient17":null, "strIngredient18":null, "strIngredient19":null, "strIngredient20":null, "strMeasure1":"175g\\/6oz", "strMeasure2":"75g\\/3oz", "strMeasure3":"200g\\/7oz", "strMeasure4":"75g\\/3oz", "strMeasure5":"75g\\/3oz", "strMeasure6":"2", "strMeasure7":"75g\\/3oz", "strMeasure8":"1 tsp", "strMeasure9":"50g\\/1\¾oz", "strMeasure10":"", "strMeasure11":"", "strMeasure12":"", "strMeasure13":"", "strMeasure14":"", "strMeasure15":"", "strMeasure16":null, "strMeasure17":null, "strMeasure18":null, "strMeasure19":null, "strMeasure20":null }; const { idMeal, strMeal, strDrinkAlternate, strCategory, ...rest } = data; console.log(rest);

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