Skip to content
Advertisement

Laravel access data from JSON object in multiple dimensions

I’m writing a Laravel API that consumes an already existing API. I need my own “middleman” API since it inserts sensitive data before sending the request because I don’t want to store that sensitive data on the client side.

I can fetch the data alright and all that, but I would like to be able to use route parameters to access various “dimensions” of the returned JSON object.

Currently, if I navigate to /get/status I get a response that looks like this.

{
    "fuelAmount": 8,
    "fuelAmountLevel": 11,

    "tyrePressure": {
        "frontLeftTyrePressure": "Normal",
        "frontRightTyrePressure": "Normal",
        "rearLeftTyrePressure": "Normal",
        "rearRightTyrePressure": "Normal",
        "timestamp": "2020-05-19T20:10:49+0000"
    },

    "heater": {
        "seatSelection": {
            "frontDriverSide": false,
            "frontPassengerSide": false,
            "rearDriverSide": false,
            "rearPassengerSide": false,
            "rearMid": false
        },
        "status": "off",
        "timer1": {
            "time": "17:30",
            "state": false
        },
        "timer2": {
            "time": "00:00",
            "state": false
        },
        "timestamp": "2020-05-19T11:28:19+0000"
    },
}

What I would like to be able to do is navigate to get/status/fuelAmount and only get the fuelAmount back. So I would only get 8 as a response. Currently I am able to do this, but I am not sure how to do this on multiple levels in an efficient way. Because getting the fuelAmount is just one “level deeper”, I also wanna be able to do /get/status/heater/timer1/time and only get 17:30 as the response.

Currently the code looks like this

public function vehicleGet($vMethod, $dataKey= null) {
    $response = Http::withHeaders([
        // bunch of headers needed to successfully request data
    ])
    ->withBasicAuth("user", config('app.mySecret'))
    ->get($this->url);

    if(isset($dataKey)) {
        return $response[$dataKey];
    }else {
        return $response->json();;
    }
}

The route in Laravel

Route::get("get/{vMethod}/{dataKey?}", "DashController@vehicleGet")->where('dataKey', '.*');

So like I said, if I go to /get/status/heater I successfully request the status endpoint of the 3rd-party API and I am able to print out only the heater data.

{
    "seatSelection": {
        "frontDriverSide": false,
        "frontPassengerSide": false,
        "rearDriverSide": false,
        "rearPassengerSide": false,
        "rearMid": false
    },
    "status": "off",
    "timer1": {
    "    time": "17:30",
    "    state": false
    },
    "timer2": {
        "time": "00:00",
        "state": false
    },
    "timestamp": "2020-05-19T11:28:19+0000"
}

But if I go to /get/status/heater/timer1/ I get Undefined index: heater/timer1 because obviously that key doesn’t exist in the initial JSON object.

So I would have to somehow add more keys to this return statement return $response[$dataKey] depending on the dataKey parameter in the URL. I can explode that string and get an array with each individual key but I still need to somehow add each key to the return statement..

I can add more parameters in the route instead of using a single wildcard parameter but then I need to write a bunch of if statements for each of the optional parameters, check if it is set and if it is, use it as a key when displaying the JSON data?

Advertisement

Answer

Replace your current isset code block with the following:

if(isset($dataKey)) 
{
    $dt = $response;
    $searchFound = 1;
    $dataKey = explode("/" , $dataKey);
    foreach($dataKey as $key => $val)
    {
        if(isset($dt[$val])) 
        {
          $dt = $dt[$val];
        } else 
        {
          $searchFound = 0;
          break;
        }
    }

    return $dt;

}else {
    return $response->json();;
}

User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement