4

Please look into EDIT at the end.

I am parsing invalid json data from an external URL and I want modify the values of a specific keys. I want to multiply the values with a constant number for the values of a specific key (cent).

If you look closely, the pattern repeats, it starts with "vk".

How can I multiply the values of "cent" with a constant number (0.887).

The sample data that I'm parsing from external URL looks like as shown below:

{"0":{"vk":{"cent":21,"bank":1453},"ok":{"cent":4,"bank":2581},"wa":{"cent":4.5,"bank":959},"vi":{"cent":4,"bank":0},"tg":{"cent":4.5,"bank":0},"wb":{"cent":14,"bank":6733},"go":{"cent":5.5,"bank":149},"av":{"cent":2.5,"bank":2139},"av_1":{"cent":59,"bank":0},"fb":{"cent":3,"bank":84},"tw":{"cent":2,"bank":3848},"ot_1":{"cent":59,"bank":0},"ub":{"cent":1,"bank":4042},"gt":{"cent":1,"bank":6835},"ig":{"cent":5,"bank":3094},"ym":{"cent":2,"bank":16},"ym_1":{"cent":59,"bank":0},"ma":{"cent":1,"bank":5282},"mm":{"cent":2,"bank":0},"uk":{"cent":2,"bank":7097},"mb":{"cent":2.5,"bank":2694},"we":{"cent":1,"bank":7010},"bd":{"cent":13,"bank":0},"dt":{"cent":2,"bank":5592},"ya":{"cent":2,"bank":3811},"ya_1":{"cent":59,"bank":0},"mt":{"cent":4,"bank":6468},"oi":{"cent":1.25,"bank":1200},"fd":{"cent":1,"bank":5505},"zz":{"cent":2,"bank":7097},"kt":{"cent":1.5,"bank":6585},"pm":{"cent":1.5,"bank":983},"tn":{"cent":1,"bank":7112},"qq":{"cent":2,"bank":5796},"mg":{"cent":1,"bank":2260},"yl":{"cent":1,"bank":5950},"po":{"cent":2,"bank":5645},"nv":{"cent":2,"bank":3378},"nf":{"cent":2,"bank":6210},"im":{"cent":1.5,"bank":217},"ds":{"cent":1.25,"bank":5796},"vv":{"cent":1,"bank":6685},"lf":{"cent":1.5,"bank":6582},"gp":{"cent":1.5,"bank":6682},"am":{"cent":1,"bank":6674},"tc":{"cent":1,"bank":6683},"dp":{"cent":1,"bank":6324},"yf":{"cent":2,"bank":6587},"op":{"cent":2,"bank":6331},"fx":{"cent":2,"bank":6525},"qr":{"cent":2,"bank":6664},"yk":{"cent":2,"bank":6650},"ls":{"cent":2,"bank":6668},"bl":{"cent":2,"bank":6025},"mu":{"cent":2,"bank":6627},"fu":{"cent":2,"bank":6666},"sg":{"cent":2,"bank":6387},"uu":{"cent":2,"bank":6678},"ua":{"cent":2,"bank":6357},"ab":{"cent":2,"bank":6127},"iv":{"cent":2,"bank":6685},"fy":{"cent":2,"bank":6351},"ce":{"cent":2,"bank":6279},"hm":{"cent":2,"bank":6317},"tx":{"cent":2,"bank":6669},"pl":{"cent":2,"bank":6682},"ip":{"cent":2,"bank":6314},"hw":{"cent":2,"bank":6085},"de":{"cent":1,"bank":6548},"jc":{"cent":2,"bank":6683},"rl":{"cent":2,"bank":6594},"df":{"cent":2,"bank":6353},"ui":{"cent":1.5,"bank":6633},"up":{"cent":2,"bank":6670},"kf":{"cent":1,"bank":6685},"za":{"cent":2,"bank":6683},"da":{"cent":3,"bank":5469},"sq":{"cent":2,"bank":6685},"li":{"cent":2,"bank":6486},"rd":{"cent":2,"bank":6650},"qb":{"cent":2,"bank":6685},"hz":{"cent":2,"bank":6684},"ia":{"cent":2,"bank":6685},"ew":{"cent":1.5,"bank":6681},"ae":{"cent":1,"bank":6654},"gb":{"cent":1,"bank":6681},"cy":{"cent":3,"bank":5642},"qm":{"cent":2.5,"bank":6684},"yb":{"cent":2.5,"bank":6761},"ot":{"cent":2.5,"bank":0}}}{"1":{"vk":{"cent":21,"bank":6},"ok":{"cent":5,"bank":1594},"wa":{"cent":8,"bank":0},"vi":{"cent":7,"bank":3},"tg":{"cent":8,"bank":0},"wb":{"cent":15,"bank":952},"go":{"cent":10,"bank":2},"av":{"cent":4,"bank":1517},"fb":{"cent":3.5,"bank":3},"tw":{"cent":2,"bank":453},"ub":{"cent":2,"bank":610},"gt":{"cent":1,"bank":1511},"sn":{"cent":40,"bank":693},"ig":{"cent":6,"bank":0},"ss":{"cent":1,"bank":1516},"ym":{"cent":2,"bank":1434},"ma":{"cent":1,"bank":1140},"mm":{"cent":2,"bank":0},"uk":{"cent":2,"bank":1447},"me":{"cent":1,"bank":1516},"mb":{"cent":2.5,"bank":262},"we":{"cent":1,"bank":1517},"bd":{"cent":1,"bank":1509},"kp":{"cent":2,"bank":1466},"dt":{"cent":1,"bank":1515},"ya":{"cent":1,"bank":558},"mt":{"cent":4,"bank":1923},"oi":{"cent":2,"bank":474},"fd":{"cent":2,"bank":1448},"zz":{"cent":2,"bank":1509},"kt":{"cent":2,"bank":580},"pm":{"cent":1.5,"bank":1},"tn":{"cent":1,"bank":1499},"qq":{"cent":2,"bank":1022},"yl":{"cent":1,"bank":1459},"po":{"cent":6,"bank":1478},"nv":{"cent":6,"bank":611},"nf":{"cent":6,"bank":1334},"im":{"cent":2,"bank":188},"ds":{"cent":1.5,"bank":187},"vv":{"cent":2,"bank":1453},"ji":{"cent":2,"bank":998},"lf":{"cent":2,"bank":1470},"hu":{"cent":6,"bank":854},"wg":{"cent":4,"bank":991},"rz":{"cent":2,"bank":1408},"la":{"cent":6,"bank":1477},"zh":{"cent":1,"bank":1430},"gp":{"cent":1.5,"bank":1458},"ls":{"cent":6,"bank":1478},"zy":{"cent":6,"bank":1476},"tx":{"cent":6,"bank":1260},"cm":{"cent":6,"bank":1384},"hw":{"cent":6,"bank":853},"ri":{"cent":9,"bank":1476},"za":{"cent":2,"bank":1453},"gl":{"cent":3,"bank":1366},"dh":{"cent":4,"bank":1409},"ot":{"cent":6,"bank":519}}}

The code I tried:

$json = get_content('tld.xyz/json.php?bank=prices'); 
$data = json_decode($json, true); 
foreach ($decoded_json['cent'] as &$value) 
{ if ($value >= 0){ $value = $value * 0.887; $result[]=$value; } } 
$fin = json_encode($data); 
echo $fin;

EDIT: I think it's not json and it can be solved by using regex. I am thinking to find the string between : and , and how to multiply this number with my constant.

Any help is appreciated. I am not a web developer but I have a small project and I'm trying to solve this issue on my own rather than hiring someone.

Thank you.

mdhz
  • 113
  • 1
  • 10
  • I am able to extract and decode json but searching for key's values and multiplying is what I need. I already saw many similar question but mine is different. – mdhz May 02 '20 at 07:23
  • I tried this code as it seemed similar problem like mine but the result I got is still the same. https://stackoverflow.com/a/38880531/9488870 Code I used: $json = get_content('https://tld.xyz/json.json'); $data = json_decode($json, true); foreach ($decoded_json['cost'] as &$value) { if ($value >= 0){ $value = $value * 2; $result[]=$value; } } $fin = json_encode($data); echo $fin; – mdhz May 02 '20 at 07:36
  • I tried this as well https://stackoverflow.com/a/17806269/9488870 But it's different as it's looking into the constant key value itself but I need to change that key value. – mdhz May 02 '20 at 07:37
  • Sorry, it should had been cent. Oh, I didn't knew it's invalid json. Any work around so that I can search for "cent" and multiply the existing value with constant number? – mdhz May 02 '20 at 07:47
  • I cross checked the source json on that website and it said valid JSON and I don't see the square brackets [] in the source website, but while parsing in php using get_content() is adding those brackets, unsure why. The source has this at the start - {"0":{vk... – mdhz May 02 '20 at 07:57
  • Yeah, I read the help docs after I got that message. I need to wait for 6 months or I can try to improve my questions (which I don't know how). – mdhz May 02 '20 at 09:28
  • Yes, I'm calling get_content() multiple times. @GrahamRitchie – mdhz May 02 '20 at 10:10
  • 1
    `/cent":(\d*),/` (flags gm) thats the regex you need in order to capture your numbers into group $1 - then use `preg_replace`. Sorry on mobile so I can't write full answer (well I can but it is too much of a pain, hard enough typing the regex!). – GrahamTheDev May 02 '20 at 10:14
  • Thank you @GrahamRitchie I'll play around with these hints. Feel free to answer later. – mdhz May 02 '20 at 10:17
  • 1
    also your get_content multiple times is why your JSON is invalid. You may be better looking at converting the JSON to an array each time you call it and merging the arrays (then you can manipulate your data in PHP) and then revert back to JSON. – GrahamTheDev May 02 '20 at 10:18
  • Alright thanks. I will try doing this, I'm not well versed with PHP development but I will give it a try. – mdhz May 02 '20 at 10:20
  • 1
    hi there mdhz - i am still learning php. one question though: did the solution of bestprogrammerintheworld finally did it - did it work for you. Love to hear from you – zero May 19 '20 at 17:13
  • @zero Sorry for late reply, it did work. I've marked it as answer also. – mdhz Jun 05 '20 at 03:44

1 Answers1

2
<?php
$json = '{"0":{"vk":{"cent":21,"bank":1453},"ok":{"cent":4,"bank":2581},"wa":{"cent":4.5,"bank":959},"vi":{"cent":4,"bank":0},"tg":{"cent":4.5,"bank":0},"wb":{"cent":14,"bank":6733},"go":{"cent":5.5,"bank":149},"av":{"cent":2.5,"bank":2139},"av_1":{"cent":59,"bank":0},"fb":{"cent":3,"bank":84},"tw":{"cent":2,"bank":3848},"ot_1":{"cent":59,"bank":0},"ub":{"cent":1,"bank":4042},"gt":{"cent":1,"bank":6835},"ig":{"cent":5,"bank":3094},"ym":{"cent":2,"bank":16},"ym_1":{"cent":59,"bank":0},"ma":{"cent":1,"bank":5282},"mm":{"cent":2,"bank":0},"uk":{"cent":2,"bank":7097},"mb":{"cent":2.5,"bank":2694},"we":{"cent":1,"bank":7010},"bd":{"cent":13,"bank":0},"dt":{"cent":2,"bank":5592},"ya":{"cent":2,"bank":3811},"ya_1":{"cent":59,"bank":0},"mt":{"cent":4,"bank":6468},"oi":{"cent":1.25,"bank":1200},"fd":{"cent":1,"bank":5505},"zz":{"cent":2,"bank":7097},"kt":{"cent":1.5,"bank":6585},"pm":{"cent":1.5,"bank":983},"tn":{"cent":1,"bank":7112},"qq":{"cent":2,"bank":5796},"mg":{"cent":1,"bank":2260},"yl":{"cent":1,"bank":5950},"po":{"cent":2,"bank":5645},"nv":{"cent":2,"bank":3378},"nf":{"cent":2,"bank":6210},"im":{"cent":1.5,"bank":217},"ds":{"cent":1.25,"bank":5796},"vv":{"cent":1,"bank":6685},"lf":{"cent":1.5,"bank":6582},"gp":{"cent":1.5,"bank":6682},"am":{"cent":1,"bank":6674},"tc":{"cent":1,"bank":6683},"dp":{"cent":1,"bank":6324},"yf":{"cent":2,"bank":6587},"op":{"cent":2,"bank":6331},"fx":{"cent":2,"bank":6525},"qr":{"cent":2,"bank":6664},"yk":{"cent":2,"bank":6650},"ls":{"cent":2,"bank":6668},"bl":{"cent":2,"bank":6025},"mu":{"cent":2,"bank":6627},"fu":{"cent":2,"bank":6666},"sg":{"cent":2,"bank":6387},"uu":{"cent":2,"bank":6678},"ua":{"cent":2,"bank":6357},"ab":{"cent":2,"bank":6127},"iv":{"cent":2,"bank":6685},"fy":{"cent":2,"bank":6351},"ce":{"cent":2,"bank":6279},"hm":{"cent":2,"bank":6317},"tx":{"cent":2,"bank":6669},"pl":{"cent":2,"bank":6682},"ip":{"cent":2,"bank":6314},"hw":{"cent":2,"bank":6085},"de":{"cent":1,"bank":6548},"jc":{"cent":2,"bank":6683},"rl":{"cent":2,"bank":6594},"df":{"cent":2,"bank":6353},"ui":{"cent":1.5,"bank":6633},"up":{"cent":2,"bank":6670},"kf":{"cent":1,"bank":6685},"za":{"cent":2,"bank":6683},"da":{"cent":3,"bank":5469},"sq":{"cent":2,"bank":6685},"li":{"cent":2,"bank":6486},"rd":{"cent":2,"bank":6650},"qb":{"cent":2,"bank":6685},"hz":{"cent":2,"bank":6684},"ia":{"cent":2,"bank":6685},"ew":{"cent":1.5,"bank":6681},"ae":{"cent":1,"bank":6654},"gb":{"cent":1,"bank":6681},"cy":{"cent":3,"bank":5642},"qm":{"cent":2.5,"bank":6684},"yb":{"cent":2.5,"bank":6761},"ot":{"cent":2.5,"bank":0}}}{"1":{"vk":{"cent":21,"bank":6},"ok":{"cent":5,"bank":1594},"wa":{"cent":8,"bank":0},"vi":{"cent":7,"bank":3},"tg":{"cent":8,"bank":0},"wb":{"cent":15,"bank":952},"go":{"cent":10,"bank":2},"av":{"cent":4,"bank":1517},"fb":{"cent":3.5,"bank":3},"tw":{"cent":2,"bank":453},"ub":{"cent":2,"bank":610},"gt":{"cent":1,"bank":1511},"sn":{"cent":40,"bank":693},"ig":{"cent":6,"bank":0},"ss":{"cent":1,"bank":1516},"ym":{"cent":2,"bank":1434},"ma":{"cent":1,"bank":1140},"mm":{"cent":2,"bank":0},"uk":{"cent":2,"bank":1447},"me":{"cent":1,"bank":1516},"mb":{"cent":2.5,"bank":262},"we":{"cent":1,"bank":1517},"bd":{"cent":1,"bank":1509},"kp":{"cent":2,"bank":1466},"dt":{"cent":1,"bank":1515},"ya":{"cent":1,"bank":558},"mt":{"cent":4,"bank":1923},"oi":{"cent":2,"bank":474},"fd":{"cent":2,"bank":1448},"zz":{"cent":2,"bank":1509},"kt":{"cent":2,"bank":580},"pm":{"cent":1.5,"bank":1},"tn":{"cent":1,"bank":1499},"qq":{"cent":2,"bank":1022},"yl":{"cent":1,"bank":1459},"po":{"cent":6,"bank":1478},"nv":{"cent":6,"bank":611},"nf":{"cent":6,"bank":1334},"im":{"cent":2,"bank":188},"ds":{"cent":1.5,"bank":187},"vv":{"cent":2,"bank":1453},"ji":{"cent":2,"bank":998},"lf":{"cent":2,"bank":1470},"hu":{"cent":6,"bank":854},"wg":{"cent":4,"bank":991},"rz":{"cent":2,"bank":1408},"la":{"cent":6,"bank":1477},"zh":{"cent":1,"bank":1430},"gp":{"cent":1.5,"bank":1458},"ls":{"cent":6,"bank":1478},"zy":{"cent":6,"bank":1476},"tx":{"cent":6,"bank":1260},"cm":{"cent":6,"bank":1384},"hw":{"cent":6,"bank":853},"ri":{"cent":9,"bank":1476},"za":{"cent":2,"bank":1453},"gl":{"cent":3,"bank":1366},"dh":{"cent":4,"bank":1409},"ot":{"cent":6,"bank":519}}}';

//JSON supplied is not valid, it misses [] at the beginning and the end
//and it also misses a comma between the keys which is solved by next two lines
$json = str_replace("}{","},{", $json);
$valid_json = '[' . $json . ']';

$data = json_decode($valid_json, true); 

//Copy the current data into new array $na
$na = array_slice($data,0,count($data));

//Change the copy of array $data with cents
foreach($data as $top_key=>$value) {
    $level_arr = $na[$top_key][$top_key];    
    foreach($level_arr as $key=>$item) {
        if ($na[$top_key][$top_key][$key]['cent']>0) {
            $na[$top_key][$top_key][$key]['cent'] = $data[$top_key][$top_key][$key]['cent'] * 0.087;
        }
    }
}

//JSON
echo json_encode($na);

UPDATE1:

You could remove if ($na[$top_key][$top_key][$key]['cent']>0) { - part.

//Change the copy of array $data with cents
foreach($data as $top_key=>$value) {
    $level_arr = $na[$top_key][$top_key];    
    foreach($level_arr as $key=>$item) {
            $na[$top_key][$top_key][$key]['cent'] = $data[$top_key][$top_key][$key]['cent'] * 0.087; 
    }
}

//JSON
echo json_encode($na);

UPDATE2:

Above require that the levels of the array are:

[0][0][{whatever key}]['cent]
[1][1][{whatever key}]['cent]
[2][2][{whatever key}]['cent]

If you want more flexibility for not being depent that top level key and the second level key are the same ( [0][0], [1][1] etc... )

You could do this: (replace the code given above)

//Change the copy of array $data with cents
foreach($data as $top_key=>$second_level) {
    foreach($second_level as $key2=>$value) {
        $level_arr = $na[$top_key][$key2];    
        foreach($level_arr as $key=>$item) {
                $na[$top_key][$key2][$key]['cent'] = (float)$data[$top_key][$key2][$key]['cent'] * 0.087;
        }
    }
}

UPDATE3:

I missed to change $top_key to $key2 in update2 (Now I corrected that to), but here is almost the same code but with result as two decimals based on the actual data (given from the external API) with cost as key instead of cent. I've also changed the actual contant to 0.877 instead of 0.087.

foreach($data as $top_key=>$second_level) {
    foreach($second_level as $key2=>$level_arr) { 
        foreach($level_arr as $key=>$item) {
            $na[$top_key][$key2][$key]['cost'] = 
            number_format(
            (float)$data[$top_key][$key2][$key]['cost'] * 0.877,2
            );
        }
    }
}
bestprogrammerintheworld
  • 5,417
  • 7
  • 43
  • 72
  • This worked but some of the key values are integer type and they're not changing, those that were strings changed. Example: array(3) { [0]=> array(1) { [7]=> array(18) { ["vk"]=> array(2) { ["cent"]=> int(10) ["bank"]=> int(0) } ["ok"]=> array(2) { ["cent"]=> int(8) ["bank"]=> int(0) } ["wa"]=> array(2) { ["cent"]=> int(18) ["bank"]=> int(88) } ["vi"]=> array(2) { ["cent"]=> int(12) ["bank"]=> int(4088) } – mdhz May 03 '20 at 06:13
  • 1
    It does not fail here, but you could cast to float: $data[$top_key][$top_key][$key]['cent'] * 0.087 TO float()$data[$top_key][$top_key][$key]['cent'] * 0.087. Does that do the trick? – bestprogrammerintheworld May 03 '20 at 06:38
  • I tried this but didn't work out. $na[$top_key][$top_key][$key]['cent'] = number_format(floatval($data[$top_key][$top_key][$key]['cent']) * 0.877, 2); as I wanted two decimals. – mdhz May 03 '20 at 08:45
  • Tell me one exact value does not work (which key, subkey etc and value)? (tell me before and after) and I might be able to help you further. – bestprogrammerintheworld May 03 '20 at 08:51
  • Your code works, the file content I'm parsing is giving me mixed values. Example: It works for array(4) { [0]=> array(1) { [0]=> array(90) { ["vk"]=> array(2) { ["cent"]=> string(4) "0.88" ["bank"]=> int(1366) } It doesn't work for array(1) { [7]=> array(18) { ["vk"]=> array(2) { ["cent"]=> int(10) ["bank"]=> int(0) } *EDIT:typo – mdhz May 03 '20 at 09:02
  • Is the data you're checking the same data as you've supplied in your original question? – bestprogrammerintheworld May 03 '20 at 09:03
  • Yes the data is the same. I parse it from external file using $json = get_content('tld.xyz/json.php?bank=prices'); multiple times with different URL parameters and then concatenating them into a single string so it has a repeating pattern and invalid json. It's working only for certain URL parameters and not working after that even though the data is same, that is, values are not changing. I thought it'll work only for 3 parameters, so I removed the json which was working and only parsed rest which was not working but it's not changing values. – mdhz May 03 '20 at 10:06
  • Here's the full code if you want to give a try. https://privnote.com/h4HvZpc2#i7qCKNvoj Current results: Second time vk cost key value is 10 and third time it's 15. Expected results: Second time vk cost key value should get 8.77 and third time 13.15 *EDIT:I'll look into the updated answer :-) – mdhz May 03 '20 at 10:55
  • Still getting same results after updating the new code. By the way if you're trying it then don't get confused with the key names. – mdhz May 03 '20 at 11:07
  • If you want 8.77 and 13.15 I suppose 0.887 is not correct. The constant should be 0.877. Look at my latest UPDATE3 now (just edited) and I think you will get what you look for :-) It return 13.16 for vk-key the third time because the actual value is 13.1550 which is displayed as 13.16 when using two decimals. – bestprogrammerintheworld May 03 '20 at 12:18
  • 1
    I must admit I set the wrong constant from the beginning which made a little bit more mess. – bestprogrammerintheworld May 03 '20 at 12:25
  • Awesome, finally working as expected. It would not have been achievable without you. Also, I wish stackoverflow had a tipping option. Thank you. – mdhz May 03 '20 at 13:48