Convert JSON IN LARAVEL - php

Here is my JSON
[
{
"TIMESTAMP": "2021-06-09 13:13:26",
"COL1": "10",
"COL2": "20",
"COL3": "30"
},
{
"TIMESTAMP": "2021-06-22 13:13:26",
"COL1": "20",
"COL2": "30",
"COL3": "40"
},
{
"TIMESTAMP": "2021-06-21 13:13:26",
"COL1": "1",
"COL2": "2",
"COL3": "3"
},
{
"TIMESTAMP": "2021-06-20 13:13:26",
"COL1": "40",
"COL2": "50",
"COL3": "60"
}
]
I need to refactor the json According to the Column name like (EXPECTED OUTPUT)
[
{
"TITLE":"COL1"
"DATA":[10,20,1,40]
},
{
"TITLE":"COL2"
"DATA":[20,30,2,50]
},
{
"TITLE":"COL3"
"DATA":[30,40,3,60]
},
]
I was tried but it not working
$data = json_decode($result, true);
$refactored = array_map(function($item) {
return (object)[
'TIMESTAMP' => $item['TIMESTAMP'],
'DATA' => [ $item['COL1'], $item['COL2'], $item['COL3'] ]
];
}, $data);
dump($refactored);
Someone help me out with this. The column may be 3 or more and it must be dynamic. Thanks in advance.

You can transform your JSON like this:
$data = json_decode($result, true);
$refactored = array_reduce($json, function($carry, $item) {
foreach($item as $key => $value) {
if (str_starts_with($key, 'COL')) {
$index = substr($key, 3, 1) - 1;
if (!isset($carry[$index])) {
$carry[$index] = [
'Title' => $key
];
}
$carry[$index]['Data'][] = $value;
}
}
return $carry;
}, []);
dump($refactored);

I am always a fan of using the value you want to group your data by as a temporary array key, that makes things easier, and can simply be reset by using array_values afterwards.
$input = json_decode('…', true);
$output = [];
foreach($input as $item) {
foreach($item as $key => $value) {
if($key != 'TIMESTAMP') {
$output[$key]['TITLE'] = $key;
$output[$key]['DATA'][] = (int)$value;
}
}
}
$output = array_values($output);
echo json_encode($output);

All you have to do is re-encode the processed data:
json_encode($refactored) will give you the output that you want.
P.S. you don't have to cast to an object. It works as array as well.

Related

PHP flatten a Multidimensional Array with keys

I wrote some PHP code to line up the children of an array. I wrote a recursive function.
Everything is listed correctly one below the other, but some arrays do not have the "Name" key.
Does anyone have any idea how I can get it to show everyone's "Name" key?
My PHP Code:
$json = '[
{
"name": "A",
"children": [
{
"name": "B",
"children": [
{
"name": "C"
},
{
"name": "D",
"children": [
{
"name": "E"
},
{
"name": "F"
}
]
}
]
},
{
"name": "G"
}
]
},
{
"name": "H"
}
]';
header('Content-Type: application/json; charset=utf-8');
$json = json_decode($json, true);
function array_flatten($array, $prefix = '') {
$return = array();
foreach ($array as $key => $value) {
if (is_array($value) && array_key_exists("children", $value)){
$return = array_merge($return, array_flatten($value, $key));
}else if (is_array($value) && count($value) > 1){
foreach ($value as $keyA => $valueA) {
if (is_array($valueA) && array_key_exists("children", $valueA)){
$return = array_merge($return, array_flatten($valueA, $keyA));
}else{
$return[] = $valueA;
}
}
} else {
$return[] = $value;
}
}
return $return;
}
echo json_encode(array_flatten($json));
Current Result:
["A","B",{"name":"C"},"D",{"name":"E"},{"name":"F"},{"name":"G"},{"name":"H"}]
What I want:
[{"name":"A"},{"name":"B"},{"name":"C"},{"name":"D"},{"name":"E"},{"name":"F"},{"name":"G"},{"name":"H"}]
Here is a working code :
<?php
$json = '[
{
"name": "A",
"children": [
{
"name": "B",
"children": [
{
"name": "C"
},
{
"name": "D",
"children": [
{
"name": "E"
},
{
"name": "F"
}
]
}
]
},
{
"name": "G"
}
]
},
{
"name": "H"
}
]';
$json = json_decode($json, true);
function getArrayValuesRecursively(array $array){
$values = [];
foreach ($array as $value) {
if (is_array($value)) {
$values = array_merge(
$values,
getArrayValuesRecursively($value)
);
} else {
$values[] = ['name' => $value];
}
}
return $values;
}
echo json_encode(getArrayValuesRecursively($json));
Demo : https://3v4l.org/01Fla
Function getArrayValuesRecursively(array $array) is from Get all values from multidimensional array
here's my take on it:
$json = json_decode($json, true);
$names = get_names_of_people($json);
print(json_encode($names));
function get_names_of_people(array $people): array
{
$names = [];
foreach ($people as $person) {
foreach ($person as $key => $value) {
switch ($key) {
case 'name':
$names[] = [
'name' => $value,
];
break;
case 'children':
$names = array_merge($names, get_names_of_people($value));
}
}
}
return $names;
}
$array = json_decode($json, true);
$result = [];
array_walk_recursive($array, function ($value, $key) use(&$result) {
$result[][$key] = $value;
});

PHP change a function from from loops to recursion

I have the following JSON object:
{
"id": 1,
"name": null,
"block": {
"type": "none",
"descends": [
{
"operation":"sum",
"descends":[
{
"label":2,
"value":false
}
]
},
{
"label": 1,
"value": 3,
},
{
"label": 2,
"value": 2
}
],
"label": 1,
"value": true
}
}
I want to collect all the label and value attributes and store them in an array, so I created the following function:
public function collectValues($arr){
$finalValues = [];
foreach($arr as $key => $element){
if($key=='block'){
foreach($element as $key2 => $block){
if($key2=='descends'){
foreach($block as $key3 => $node_block){
if($key3=='descends'){
foreach($node_block as $key4 => $anotherNode){
if($key4 == 'descends'){
foreach($anotherNode as $finalNode){
$finalValues [] = array('lable'=>$finalNode->label, 'value' =>$finalNode->value);
}
}
}
}
else{
$finalValues [] = array('lable' => $node_block->label, 'value' => $node_block->value);
}
}
}
}
$finalValues [] = array('lable'=> $element->label, 'value' => $element->value);
}
}
return $finalValues;
}
The function works and I get the following:
[
{
"lable": 2,
"value": false
},
{
"lable": 1,
"value": 3
},
{
"lable": 2,
"value": 2
},
{
"lable": 1,
"value": true
}
]
The problem is that the JSON object can contain more descends like:
{
"id": 1,
"name": null,
"block": {
"type": "none",
"descends": [
{
"operation":"sum",
"descends":[
{
"operation":"sum",
"descends":[
{
"label":2,
"value":false
}
],
"label":2,
"value":false
}
]
},
{
"operation":"sum",
"descends":[
{
"label":2,
"value":false
}
],
"label": 1,
"value": 3,
},
{
"label": 2,
"value": 2
}
],
"label": 1,
"value": true
}
}
This means I will have to add more foreach loops. A good way to handle such a situation is by using recursive. How can I transform the function above into a recursive one?
Your looped function does not make sense to change. Easier to rewrite from scratch
Here is my use case for recursion. Maybe there is an easier option, but I didn’t chase optimization
$array = json_decode($json, true); //in $json your JSON)
$result = []; // array for result
checkLabel($array, $result);
print_r($result);
function checkLabel(array $array, &$result){
//first check every element on nested array
foreach ($array as $key => $value){
if (is_array($value)) {
//if found call recursive function
checkLabel($value, $result);
}
}
//then check 'label' key.. its mean we have attribute
if (array_key_exists('label', $array)) {
//save it
$result[] = [
'label' => $array['label'],
'value' => $array['value']??'' //if have label but without value)
];
}
}

merge object in php

i have below json data
{
"data": [
{
"minggu a": "2",
"total a": "377033"
},
{
"minggu b": "1",
"total b": "136615"
}
]
and this is the code i made in controller
$satu= $this->model->db_week_resTender();
$arr = [];
foreach($satu as $val){
$arr['data'][] = array(
'minggu' => $val['minggu'],
'total' => $val['total']
);
}
$response = $this->set_response($arr,200);
}
how to concatenate below json data
here I issue data with a limit of 2.
{
"data": [
{
"minggu a": "2",
"total a": "377033"
"minggu b": "1",
"total b": "136615"
},
]
}
$data = '{
"data": [
{
"minggu a": "2",
"total a": "377033"
},{
"minggu b": "1",
"total b": "136615"
}
]
}';
$decoded_satu=json_decode($data,true);
$arr = [];
foreach($decoded_satu['data'] as $key=> $val){
foreach ($val as $subkey => $subvalue) {
$arr['data'][$subkey] = $subvalue;
}
}
$finalArray = json_encode($arr);
echo "<pre>";print_r($finalArray) ;die;
foreach($statu as $index => $val){
$arr['data'][$index] = $val;
}
This should give the result you have posted at the end.

Group array objects by properties

How to group array by 'tax'and 'concept' and SUM attribute 'val'?
I looking for create a single object when tax and concept are the same, also SUM the val.
I tried with simple foreach and validation inside, but doesnt work.
thanks.
echo json_encode($array);
Array Print
[
{
"tax": "10",
"concept": "TUC",
"val": "10"
},
{
"tax": "10",
"concept": "TUC",
"val": "86"
},
{
"tax": "15",
"concept": "TUC",
"val": "8"
},
{
"tax": "11",
"concept": "IPS",
"val": "6"
},
{
"tax": "11",
"concept": "IPS",
"val": "45"
}
]
Expected Result
[
{
"tax": "10",
"concept": "TUC",
"val": "96"
},
{
"tax": "15",
"concept": "TUC",
"val": "8"
},
{
"tax": "11",
"concept": "IPS",
"val": "51"
}
]
You can use array_reduce() here. You'll use the tax value as a key you're grouping on, and reduce the array to unique tax elements while simultaneously producing the sum of val values. The only caveat with this approach is that transforming it to JSON will make PHP think that the outer element is an object and not an array (even though it is an array, this is because we end up using non-default array indexing). But, this is easily mitigated with a call to array_values().
$array = // your array from above
$result = array_reduce($array, function($carry, $item) {
if(!isset($carry[$item->tax])) {
$carry[$item->tax] = $item;
} else {
$carry[$item->tax]->val += $item->val;
}
return $carry;
});
$result = array_values($result);
echo json_encode($result);
You can see from this demo that it produces:
[{
"tax": "10",
"concept": "TUC",
"val": 96
}, {
"tax": "15",
"concept": "TUC",
"val": "8"
}, {
"tax": "11",
"concept": "IPS",
"val": 51
}]
$array // Your array
$result = [];
array_walk($array, function($object) use (&$result) {
$notExist = true;
foreach ($result as $item) {
if ($item->tax == $object->tax && $item->concept == $object->concept) {
$item->val += $object->val;
$notExist = false;
break;
}
}
if ($notExist) {
array_push($result, $object);
}
});
echo json_encode($result);
First group the objects:
$groups = [];
foreach($array as $object){
$groups[$object->tax . "\0" . $object->concept] = $object;
// I use the NUL byte to delimit, assuming it is absent in $tax and $concept
}
Then map each group into a summed-up object.
$output = array_map(function(array $group){
$object = new stdClass;
$object->tax = $group[0]->tax;
$object->concept = $group[0]->concept;
$object->val = array_reduce($group, function($carry, $item){
return $carry + $item->val;
}, 0);
return $object;
}, $groups);
<?php
$arr_str = '[
{"tax":"10", "concept":"TUC", "val":"10"},
{"tax":"10", "concept":"TUC", "val":"86"},
{"tax":"15", "concept":"TUC", "val":"8"},
{"tax":"11", "concept":"IPS", "val":"6"},
{"tax":"11", "concept":"IPS", "val":"45"}
]';
$arr = json_decode($arr_str);
$tmp_array = [];
foreach ($arr as $e) {
// combine "tax" and "concept" so we can use both of them as key. Use "_" as delimiter.
$key = $e->tax . "_" . $e->concept;
// sum the "val" if the key exists, otherwise assign it
isset($tmp_array[$key]) ? $tmp_array[$key] += $e->val : $tmp_array[$key] = $e->val;
}
$grouped_array = [];
foreach ($tmp_array as $k => $v) {
// ungroup the key so we can create an array like the original one
$tmp = explode("_", $k);
$grouped_array[] = (object)["tax" => $tmp[0], "concept" => $tmp[1], "val" => $v];
}
echo json_encode($grouped_array);
?>

How to choose first key of foreach() within a foreach()

I cant seem to get this working right it just returns each of value0. I only want the first key under data1 so the values of 1111 and 3333. If I add a key to value0 I get "1" as its value and the same number of them are displayed. In this example there are four and only two should return.
Json:
{
"json": "success",
"data": [
{
"data0": "123",
"data1": [
{
"value0": "1111",
"value1": "aaaa"
},
{
"value0": "2222",
"value1": "bbbb"
}
]
},
{
"data0": "abc",
"data1": [
{
"value0": "3333",
"value1": "cccc"
},
{
"value0": "4444",
"value1": "dddd"
}
]
}
],
"number": 300,
"end": ""
}
PHP:
foreach( $json->data as $data) {
foreach($data->data1 as $value) {
echo "{$value->value0}<br>";
}
}
if you want both array 0 index
$json = json_decode($json, true);
foreach( $json['data'] as $data) {
echo $data['data1'][0]['value0']; //11113333
}
or use directly without foreach for get one value
echo $json['data'][0]['data1'][0]['value0']; //1111
To keep your object version, you could loop like so:
$jsonObj = json_decode($json);
foreach($jsonObj as $value) {
foreach($value as $data => $object) {
echo $object->data1[0]->value0;
}
}
Should give you:
11113333

Categories