katie hudson
katie hudson

Reputation: 2893

Looping through JSON decoded data

I make a call to an API by doing the following

$widgets = json_decode(APIHelper::getWidgetsForDashboards($accessToken, $dashboards), true);

The response gives me an array of data which is quite large. I have made an example of what the response for one of the elements is like here

2 => array:23 [▼
    "title" => ""
    "type" => "smartLabel"
    "options" => array:5 [▼
      "title" => true
      "data" => array:1 [▼
        0 => array:3 [▼
          "labelName" => "Label"
          "labelValues" => array:1 [▼
            0 => "Some Name"
          ]
        ]
      ]
    ]
]

So the Job I am faced with is getting the labelValues. There are some conditions however. I only want the labelValues for objects which have a type of smartLabel. Now I have a working solution which I will show, I just feel like there is a simpler way to achieve this because my current solution involves a lot of nesting. This is what I have done

$titlesArray = array();

foreach($widgets as $widget) {
    if ($widget['type'] == 'smartLabel') {
        foreach($widget['options'] as $optionKey => $optionValue) {
            if($optionKey == 'data') {
                foreach($optionValue as $key => $value) {
                    if($key == 'labelValues') {
                        foreach($value as $labelKey => $labelValue) {
                            if($labelKey == 'labelValues') {
                                foreach($labelValue as $label) {
                                    $titlesArray[] = array(
                                        $label
                                    );
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

Is there any way to possibly clean this up?

Thanks

Upvotes: 1

Views: 57

Answers (3)

codedge
codedge

Reputation: 5164

Just for the sake of considering working with Laravel collections you can convert your array and use the nice options the collections give you.

$titlesArray = collect($widgets)->filter(function ($widget) {
    return $widget['type'] === 'smartLabel';
})->pluck('options')
  ->pluck('data')
  ->flatten(1)
  ->pluck('labelValues')
  ->flatten();

Upvotes: 1

jeroen
jeroen

Reputation: 91734

You can get rid of two levels by looping over $widget['options']['data'] and $value['labelValues'].

That would also remove two levels of conditional statements.

And then you can also use array_merge() to get all lableValues in one go.

Something like (untested...):

foreach($widgets as $widget) {
    if ($widget['type'] === 'smartLabel') {
        foreach($widget['options']['data'] as $key => $value) {
              $titlesArray = array_merge($titlesArray, $value['labelValues']);
        }
    }
}

Upvotes: 1

Steve
Steve

Reputation: 20469

Yes you can reduce the nesting by only itterating the arrays with unknown (eg the numerical) keys, and using a negative if clause:

$titlesArray = array();

foreach($widgets as $widget) {

    if ($widget['type'] != 'smartLabel') continue;

    foreach($widget['options']['data'] as $dataItem) {
        foreach($dataItem['lableValues'] as $value) {
                    $titleArray[]=$value;
        }
    }
}

Upvotes: 1

Related Questions