dai007uk
dai007uk

Reputation: 148

Handling differences in JSON nested arrays

JSON Data Snippet

    "calcNutrients": [
      {
        "name": "Energy (kJ)",
        "valuePer100": "2557",
        "valuePerServing": "596"
      },
      {
        "name": "Energy (kcal)",
        "valuePer100": "615",
        "valuePerServing": "143"
      },
      {
        "name": "Fat (g)",
        "valuePer100": "46.2",
        "valuePerServing": "10.8"
      },
      {
        "name": " of which saturates (g)",
        "valuePer100": "16.4",
        "valuePerServing": "3.8"
      },
      {
        "name": "Carbohydrate (g)",
        "valuePer100": "0.2",
        "valuePerServing": "0.1",
        "qualPerServing": "<"
      },
      {
        "name": " of which sugars (g)",
        "valuePer100": "0.1",
        "valuePerServing": "0.1",
        "qualPerServing": "<"
      },
      {
        "name": "Protein (g)",
        "valuePer100": "49.7",
        "valuePerServing": "11.6"
      },
      {
        "name": "Salt (g)",
        "valuePer100": "3",
        "valuePerServing": "0.7"
      }
    ]
  }

I am outputting to a table at the moment which has 9 columns

kJ | Kcal | Fat | Fat Sats | Carbs | Carbs Sugar | Fibre | Protein | Salt

As you can see from the snippet above there is no Fibre listed which is causing me the problem and hence the question.

How can I deal with this so that I can present 0 if Fibre is not present in the JSON? But still populate the table correctly.

JSON is in the same order as the table column headings but some may not be present.

I just can't get my head around it

Edit:

Added code for inserting the nutrient information into the table. Table is simple HTML table with HTML hardcoded columns/headers etc (the table structure is NOT populated from the JSON

foreach ($obj2['products'][0]['calcNutrition']['calcNutrients'] as $nutrients) {
  echo "<td>" . $nutrients[$valuePerServing] . "</td>";
}

print_r result (no fibre)

Array ( [0] => Array ( [name] => Energy (kJ) [valuePer100] => 2557 [valuePerServing] => 596 )
[1] => Array ( [name] => Energy (kcal) [valuePer100] => 615 [valuePerServing] => 143 )
[2] => Array ( [name] => Fat (g) [valuePer100] => 46.2 [valuePerServing] => 10.8 )
[3] => Array ( [name] => of which saturates (g) [valuePer100] => 16.4 [valuePerServing] => 3.8 )
[4] => Array ( [name] => Carbohydrate (g) [valuePer100] => 0.2 [valuePerServing] => 0.1 [qualPerServing] => < )
[5] => Array ( [name] => of which sugars (g) [valuePer100] => 0.1 [valuePerServing] => 0.1 [qualPerServing] => < )
[6] => Array ( [name] => Protein (g) [valuePer100] => 49.7 [valuePerServing] => 11.6 )
[7] => Array ( [name] => Salt (g) [valuePer100] => 3 [valuePerServing] => 0.7 ) ) 

print_r (with fibre)

Array ( [0] => Array ( [name] => Energy (kJ) [valuePer100] => 885 [valuePerServing] => 1107 )
[1] => Array ( [name] => Energy (kcal) [valuePer100] => 213 [valuePerServing] => 266 )
[2] => Array ( [name] => Fat (g) [valuePer100] => 15.2 [valuePerServing] => 19 )
[3] => Array ( [name] => saturates (g) [valuePer100] => 5.1 [valuePerServing] => 6.4 )
[4] => Array ( [name] => Carbohydrate (g) [valuePer100] => 0 [valuePerServing] => 0 )
[5] => Array ( [name] => sugars (g) [valuePer100] => 0 [valuePerServing] => 0 )
[6] => Array ( [name] => Fibre (g) [valuePer100] => 0 [valuePerServing] => 0 )
[7] => Array ( [name] => Protein (g) [valuePer100] => 19 [valuePerServing] => 23.8 )
[8] => Array ( [name] => Salt (g) [valuePer100] => 0.3 [valuePerServing] => 0.3 ) ) 

//Further Edit

Granted I can use the below and array_splice it into where I need it if it doesn't exist, but is there any other better way of doing this?. If for instance the Protein listing was missing?

$fibreInsert = array(
  array (
      "name" => "Fibre (g)",
      "valuePer100" => "0",
      "valuePerServing" => "0"
  )
);

Answered by trincot I used his advice to create the following which works perfectly.

$isFirst = true;
    foreach ($source['calcNutrients'] as $nutrients)
      {
        if ($isFirst)
        {
            $isFirst = false;
            continue;
        }
        foreach($cols as $col) {
            if (stristr($nutrients["name"],  $col))
            {
                echo "<td>"  . $nutrients[$servingType] . "</td>";
                break;
            } else {
              echo '';
            }
        }
      }

Upvotes: 2

Views: 60

Answers (1)

trincot
trincot

Reputation: 350756

Given that the items are ordered in the right order, you could do the following:

  • Define another array that has all the 9 name values that can occur, in the correct order
  • Iterate that array, while keeping an array pointer in the calcNutrients array. If the names match, then print the td element like you did, and move the array pointer. If the names do not match, then this is a sign that that particular name is missing, so print an empty td element and don't move the array pointer.

Here is the code:

$cols = Array("Energy (kJ)", "Energy (kcal)", "Fat (g)", "of which saturates (g)",
     "Carbohydrate (g)", "of which sugars (g)", "Fibre (g)", "Protein (g)", "Salt (g)");

$result = $obj2['products'][0]['calcNutrition']['calcNutrients'];

reset($result); // we're gong to use an array pointer
foreach($cols as $col) {
    if (current($result)["name"] == $col) {
        echo "<td>" . current($result)["valuePerServing"] . "</td>\n";
        next($result); // move the array pointer.
    } else {
        echo "<td></td>\n";
    }
}

Upvotes: 1

Related Questions