I am struggling to get some informations/values from a json using php conditionally. To be more detailed, this is my case: I have a json response that looks like this:
{
"IsSuccess": true,
"ResponseCode": 5000,
"ResponseMessage": "OK",
"Data": {
"result": {
"RATE_TO_ALL": [
{
"FROM_CURR_NAME": "CHF",
"TO_CURR_NAME": "TRY",
"TREND_RATE": "0",
"SELL_RATE": "45.51",
"BUY_RATE": "26.24",
"PERCENTAGE_RATE": "0.00"
},
{
"FROM_CURR_NAME": "GBP",
"TO_CURR_NAME": "TRY",
"TREND_RATE": "0",
"SELL_RATE": "50.71",
"BUY_RATE": "29.24",
"PERCENTAGE_RATE": "0.00"
},
{
"FROM_CURR_NAME": "CAD",
"TO_CURR_NAME": "CHF",
"TREND_RATE": "0",
"SELL_RATE": "0.69",
"BUY_RATE": "0.66",
"PERCENTAGE_RATE": "0.00"
},
{
"FROM_CURR_NAME": "AUD",
"TO_CURR_NAME": "TRY",
"TREND_RATE": "0",
"SELL_RATE": "26.63",
"BUY_RATE": "15.35",
"PERCENTAGE_RATE": "0.00"
},
{
"FROM_CURR_NAME": "AUD",
"TO_CURR_NAME": "GBP",
"TREND_RATE": "0",
"SELL_RATE": "0.54",
"BUY_RATE": "0.51",
"PERCENTAGE_RATE": "0.00"
},
{
"FROM_CURR_NAME": "AUD",
"TO_CURR_NAME": "CHF",
"TREND_RATE": "0",
"SELL_RATE": "0.60",
"BUY_RATE": "0.57",
"PERCENTAGE_RATE": "0.00"
},
{
"FROM_CURR_NAME": "AUD",
"TO_CURR_NAME": "CAD",
"TREND_RATE": "0",
"SELL_RATE": "0.88",
"BUY_RATE": "0.85",
"PERCENTAGE_RATE": "0.00"
},
{
"FROM_CURR_NAME": "CAD",
"TO_CURR_NAME": "TRY",
"TREND_RATE": "0",
"SELL_RATE": "30.88",
"BUY_RATE": "17.80",
"PERCENTAGE_RATE": "0.00"
},
{
"FROM_CURR_NAME": "CAD",
"TO_CURR_NAME": "GBP",
"TREND_RATE": "0",
"SELL_RATE": "0.62",
"BUY_RATE": "0.60",
"PERCENTAGE_RATE": "0.00"
},
{
"FROM_CURR_NAME": "CHF",
"TO_CURR_NAME": "GBP",
"TREND_RATE": "0",
"SELL_RATE": "0.92",
"BUY_RATE": "0.88",
"PERCENTAGE_RATE": "0.00"
},
{
"FROM_CURR_NAME": "USD",
"TO_CURR_NAME": "GBP",
"TREND_RATE": "0",
"SELL_RATE": "0.83",
"BUY_RATE": "0.80",
"PERCENTAGE_RATE": "0.00"
},
{
"FROM_CURR_NAME": "USD",
"TO_CURR_NAME": "TRY",
"TREND_RATE": "0",
"SELL_RATE": "33.89",
"BUY_RATE": "22.92",
"PERCENTAGE_RATE": "0.00"
},
{
"FROM_CURR_NAME": "CHF",
"TO_CURR_NAME": "ALL",
"TREND_RATE": "0",
"SELL_RATE": "110.85",
"BUY_RATE": "107.10",
"PERCENTAGE_RATE": "0.00"
},
{
"FROM_CURR_NAME": "CAD",
"TO_CURR_NAME": "ALL",
"TREND_RATE": "0",
"SELL_RATE": "72.90",
"BUY_RATE": "70.40",
"PERCENTAGE_RATE": "0.00"
},
{
"FROM_CURR_NAME": "AUD",
"TO_CURR_NAME": "EUR",
"TREND_RATE": "0",
"SELL_RATE": "0.62",
"BUY_RATE": "0.60",
"PERCENTAGE_RATE": "0.00"
},
{
"FROM_CURR_NAME": "AUD",
"TO_CURR_NAME": "ALL",
"TREND_RATE": "0",
"SELL_RATE": "64.75",
"BUY_RATE": "62.55",
"PERCENTAGE_RATE": "0.00"
},
{
"FROM_CURR_NAME": "CHF",
"TO_CURR_NAME": "EUR",
"TREND_RATE": "0",
"SELL_RATE": "1.05",
"BUY_RATE": "1.02",
"PERCENTAGE_RATE": "0.00"
},
{
"FROM_CURR_NAME": "EUR",
"TO_CURR_NAME": "ALL",
"TREND_RATE": "0",
"SELL_RATE": "105.35",
"BUY_RATE": "104.75",
"PERCENTAGE_RATE": "0.00"
},
{
"FROM_CURR_NAME": "EUR",
"TO_CURR_NAME": "GBP",
"TREND_RATE": "0",
"SELL_RATE": "0.89",
"BUY_RATE": "0.85",
"PERCENTAGE_RATE": "0.00"
},
{
"FROM_CURR_NAME": "EUR",
"TO_CURR_NAME": "TRY",
"TREND_RATE": "0",
"SELL_RATE": "35.94",
"BUY_RATE": "24.90",
"PERCENTAGE_RATE": "0.00"
},
{
"FROM_CURR_NAME": "GBP",
"TO_CURR_NAME": "ALL",
"TREND_RATE": "0",
"SELL_RATE": "123.00",
"BUY_RATE": "117.35",
"PERCENTAGE_RATE": "0.00"
},
{
"FROM_CURR_NAME": "TRY",
"TO_CURR_NAME": "ALL",
"TREND_RATE": "0",
"SELL_RATE": "3.81",
"BUY_RATE": "3.10",
"PERCENTAGE_RATE": "0.00"
},
{
"FROM_CURR_NAME": "USD",
"TO_CURR_NAME": "ALL",
"TREND_RATE": "0",
"SELL_RATE": "99.10",
"BUY_RATE": "97.15",
"PERCENTAGE_RATE": "0.00"
},
{
"FROM_CURR_NAME": "USD",
"TO_CURR_NAME": "AUD",
"TREND_RATE": "0",
"SELL_RATE": "1.57",
"BUY_RATE": "1.52",
"PERCENTAGE_RATE": "0.00"
},
{
"FROM_CURR_NAME": "USD",
"TO_CURR_NAME": "CAD",
"TREND_RATE": "0",
"SELL_RATE": "1.39",
"BUY_RATE": "1.35",
"PERCENTAGE_RATE": "0.00"
},
{
"FROM_CURR_NAME": "USD",
"TO_CURR_NAME": "CHF",
"TREND_RATE": "0",
"SELL_RATE": "0.92",
"BUY_RATE": "0.89",
"PERCENTAGE_RATE": "0.00"
},
{
"FROM_CURR_NAME": "USD",
"TO_CURR_NAME": "EUR",
"TREND_RATE": "0",
"SELL_RATE": "0.95",
"BUY_RATE": "0.91",
"PERCENTAGE_RATE": "0.00"
}
],
"LASTUPDATED": "04-11-2023 14:30:03"
}
}
}
Using php, I want to retrieve value of SELL_RATE and BUY_RATE for combinations of currencies where FROM_CURR_NAME = "EUR" and TO_CURR_NAME = GBP; also FROM_CURR_NAME = "EUR" and TO_CURR_NAME = TRY; also FROM_CURR_NAME = "USD" and TO_CURR_NAME = GBP.
I have tried to get the values using $json["Data"]["result"]["RATE_TO_ALL"][17]["BUY_RATE"];
but unfortunately from the json the id [17] is changeing very offten and I am not getting the correct values. Beeing in this situation, the only solution I see is to filter json response based on combination of FROM_CURR_NAME and TO_CURR_NAME, and here I have stopped because at this moment, that is out of my league :-)
Could someone help me with a solution please? What i have now is the followings:
$url = "example.com/myjson";
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$headers = array(
"Connection: keep-alive",
'sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="96", "Google Chrome";v="96"',
"sec-ch-ua-mobile: ?0",
"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36",
'sec-ch-ua-platform: "Windows"',
"Accept: */*",
"Origin: https://www.example.com",
"Sec-Fetch-Site: same-site",
"Sec-Fetch-Mode: cors",
"Sec-Fetch-Dest: empty",
"Referer: https://www.example.com/",
"Accept-Language: en-US,en;q=0.9,sq;q=0.8,ro;q=0.7",
);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
$resp = curl_exec($curl);
curl_close($curl);
$json = json_decode($resp, true);
Thank you.
**** EDIT & UPDATED ****
After the accepted response of @Nick, I am struggling getting the foreach results in the content of another text/string that looks like this:
$numbering=1;
//Response by Nick Stackoverflow
foreach ($required_rates as ['FROM_CURR_NAME' => $from, 'TO_CURR_NAME' => $to]) {
$buy= $rates[$from][$to]['BUY_RATE'];
$sell= $rates[$from][$to]['SELL_RATE'];
//print "$from => $to : Buy $buy; Sell $sell\n";
//Adding results in an array
$foreachResultArray[] = '{ "id":'.$numbering++.', "currency":"'.$from.'", "buy":'.$buy.', "sell":'.$sell.' }';
}
//Encoding data
$encodeFullInfo = json_encode($foreachResultArray,JSON_UNESCAPED_SLASHES);
//json data that will be stored in full
$jsondata = '{
"Exchange Rates":
'.$encodeFullInfo.'
}';
And the result is as follows:
{"Exchange Rates":[
"{ "id":1, "currency":"EUR", "buy":100.55, "sell":103.45 }",
"{ "id":2, "currency":"USD", "buy":89.90, "sell":96.90 }",
"{ "id":3, "currency":"GBP", "buy":111.65, "sell":122.15 }",
"{ "id":4, "currency":"CHF", "buy":101.85, "sell":110.00 }",
"{ "id":5, "currency":"CAD", "buy":65.85, "sell":71.10 }"
]}
As you can see, the problem is that the array from the foreach statement adds quotes before the { and after the } for each result in the loop, and this makes all the statement as json invalide. What I am doing wrong at this stage? Thank you
The most efficient way (requiring only one pass over each array) to get your results is to re-index your results with the from
and to
pairs; then you can simply use that index to look up any desired rates:
$data = json_decode($resp, true);
$rates = array_reduce($data['Data']['result']['RATE_TO_ALL'], function ($acc, $item) {
$acc[$item['FROM_CURR_NAME']][$item['TO_CURR_NAME']] = array(
'SELL_RATE' => $item['SELL_RATE'],
'BUY_RATE' => $item['BUY_RATE']
);
return $acc;
}, array());
$required_rates = [
['FROM_CURR_NAME' => 'EUR', 'TO_CURR_NAME' => 'GBP'],
['FROM_CURR_NAME' => 'EUR', 'TO_CURR_NAME' => 'TRY'],
['FROM_CURR_NAME' => 'USD', 'TO_CURR_NAME' => 'GBP']
];
foreach ($required_rates as ['FROM_CURR_NAME' => $from, 'TO_CURR_NAME' => $to]) {
$buy = $rates[$from][$to]['BUY_RATE'];
$sell = $rates[$from][$to]['SELL_RATE'];
print "$from => $to : Buy $buy; Sell $sell\n";
}
Output:
EUR => GBP : Buy 0.85; Sell 0.89
EUR => TRY : Buy 24.90; Sell 35.94
USD => GBP : Buy 0.80; Sell 0.83
Demo on 3v4l.org
Note
If you're using PHP < 7.1 you won't be able to destructure the associative array, so you'll need to do:
foreach ($required_rates as $rr) {
$from = $rr['FROM_CURR_NAME'];
$to = $rr['TO_CURR_NAME'];
$buy = $rates[$from][$to]['BUY_RATE'];
$sell = $rates[$from][$to]['SELL_RATE'];
print "$from => $to : Buy $buy; Sell $sell\n";
}
Demo on 3v4l.org
Update
In terms of producing your desired output (see question edit), you are converting into JSON too often. Just build an array of results and convert to JSON once you are done:
$results = [];
$id = 1;
foreach ($required_rates as ['FROM_CURR_NAME' => $from, 'TO_CURR_NAME' => $to]) {
$buy = $rates[$from][$to]['BUY_RATE'];
$sell = $rates[$from][$to]['SELL_RATE'];
$results[] = array("id" => $id++, "currency" => $from, "buy" => $buy, "sell" => $sell);
}
$json_data = json_encode(array('Exchange Rates' => $results));
Output (for the input data):
{
"Exchange Rates": [
{
"id": 1,
"currency": "EUR",
"buy": "0.85",
"sell": "0.89"
},
{
"id": 2,
"currency": "EUR",
"buy": "24.90",
"sell": "35.94"
},
{
"id": 3,
"currency": "USD",
"buy": "0.80",
"sell": "0.83"
}
]
}
Demo on 3v4l.org