Issue formatting JSON array in PHP - php

Essentially I have the following conditionals that are made to assemble an array - the issue is the array it currently creating has too many objects.
$a = 1
$b = 2
if ($a == 1)){
$results[]['id'] = 5;
$results[]['reasons'] = "A issue";
}
if ($b == 1){
$results[]['id'] = 6;
$results[]['reasons'] = "B issue";
}
if ($b == 2){
$results[]['id'] = 6;
$results[]['reasons'] = "B issue";
}
)
$json = json_encode(array($results));
echo $json;
Current Result:
[
{
"id": 5
},
{
"reasons": "A issue"
},
{
"id": 6
},
{
"reasons": "B issue"
}
]
What I need:
[
{
"id": 5,
"reasons": "A issue"
},
{
"id": 6,
"reasons": "B issue"
}
]
How can this JSON Array be built correctly using the conditionals?

You use $results[][$value] which means push something to an array.
All you have to do is put the $id and the $reason in an array and push that array to your results, not each item individually:
$results[] = [
'id' => 5,
'message' => 'A issue'
];

You must add one object of array to your array to do that. You're actually adding strings and numbers.
CHANGE:
$results[]['id'] = 5;
$results[]['reasons'] = "A issue";
TO:
$results[] = [
'id' => 5,
'reasons' => "A issue"
];

You can write this code like this:
$a = 1;
$b = 2;
if ($a == 1){
$results[] = ['id'=> 5, 'reasons' => 'A issue'];
}
if ($b == 1){
$results[] =['id'=> 6, 'reasons' => 'B issue'];
}
if ($b == 2){
$results[] =['id'=> 6, 'reasons' => 'B issue'];
}
$json = json_encode($results);
echo $json;

Related

how to solve Array merge for json in this example?

I parse Excel sheet and get this JSON:
[
{
"A":"Samsung",
"Groupe":{
"F":"TV",
"D":"HDR"
}
},
{
"A":null,
"Groupe":{
"F":null,
"D":null
}
},
{
"A":"Sony",
"Groupe":{
"F":"T.V",
"D":"LCD"
}
},
{
"A":"Sony",
"Groupe":{
"F":"PS4",
"D":"Pro edition"
}
},
{
"A":"Sony",
"Groupe":{
"F":"Smart Phone",
"D":"Quad core"
}
}
]
Php code:
$data = [];
for ($row = 15; $row <= 25; $row++) {
$data[] = [
'A' => $worksheet->getCell('A'.$row)->getValue(),
'Groupe' => [
'F' => $worksheet->getCell('F'.$row)->getValue(),
'D' => $worksheet->getCell('D'.$row)->getValue()
]
];
}
How can I organize(sort) json depending on "A"?
I tried this but I still couldn't merge "Groupe" for same "A" together:
Take away NULL colomns.
Create a copy of the Array.
Regroup fields for same element in the new Array(this didnt work)
Code:
$data1 = [];
for ($l = 0; $l < count($data); $l++){
$data1[$l] = $data[$l];
}
for ($j = 0; $j < count($data); $j++) {
if($data[$j]['A'] != NULL){
if($data[$j]['A'] !== $data[$j+1]['A']){
$data1[$j] = $data[$j];
}
else{
$data1[$j]['A']= $data[$j]['A'];
$data1[$j]['Groupe']= array_merge($data[$j]['Groupe'], $data[$j+1]['Groupe']);
}
}
}
EDIT:
The result that I'm getting for $data1 is exactly the same as the input JSON(except that NULL was deleted), so it looks like merge Array didnt work and what I need is:
[
{
"A":"Samsung",
"Groupe":{
"F":"TV",
"D":"HDR"
}
},
{
"A":"Sony",
"Groupe": [{
"F":"T.V",
"D":"LCD"
},{
"F":"PS4",
"D":"Pro edition"
}, {"F":"Smart Phone",
"D":"Quad core"
}]
}]
Plus it's showing me this :
Notice: Undefined offset: 11 in C:\xampp\htdocs\phptoexcel.php on line
43
Line 43: if($data[$j]['A'] !== $data[$j+1]['A']){
Use the A value as key in $data, so you can group by it:
$data = [];
for ($row = 15; $row <= 25; $row++) {
//get A value, skip if A = NULL
$a = $worksheet->getCell('A'.$row)->getValue(),
if($a===NULL)continue;
//get F and D VALUE, skip if one of them = NULL
$f = $worksheet->getCell('F'.$row)->getValue();
$d = $worksheet->getCell('D'.$row)->getValue();
if($f===null || $d===null)continue;
//test if A is a key in $data. If not, create
if(!array_key_exist( $a, $data ){
$data[$a]=[
'A'=>$a,
'Groupe'=>[]
];
}
//Put F and D in a new array in Groupe
$data[$a]['Groupe'][]=["F"=>$f,"D"=>$d];
}
You will end up with:
$data=>
[ "Samsung" =>[ "A" => "Samsung",
"Groupe" => [ 0 =>[ "F" => "TV",
"D" => "HDR"
]
]
],
"Sony" => [ "A" => "Sony",
"Groupe" => [ 0 =>[ "F":"TV",
"D":"HDR"
],
1 =>[ "F":"T.V",
"D":"LCD"
],
2 =>[ "F":"PS4",
"D":"Pro edition"
],
3 =>[ "F":"Smart Phone",
"D":"Quad core"
],
]
]
Try This
$arrUnique = array();
$result = array();
$i=0;
foreach($data as $value){
if($value['A']!=null){
$data1 = [];
$intID = $value['A'];
if( in_array( $intID, $arrUnique ) ) {
$key = array_search ($intID, $arrUnique);
$result[$key]['Groupe'][] = $value['Groupe'];
}else{
$data1['A'] = $value['A'];
$data1['Groupe'][] = $value['Groupe'];
$result[$i]=$data1;
$arrUnique[]=$value['A'];
$i++;
}
}
}
I usually don't perform JSON to JSON transformation using PHP but using jq command line utility.
Given your input JSON file, you can use this jq filter:
jq '[[sort_by(.A)|.[]|select(.A!=null)]|group_by(.A)|.[]as $i|{A:$i[].A,Groupe:$i|map(.Groupe)}]|unique' file
[
{
"A": "Samsung",
"Groupe": [
{
"F": "TV",
"D": "HDR"
}
]
},
{
"A": "Sony",
"Groupe": [
{
"F": "T.V",
"D": "LCD"
},
{
"F": "PS4",
"D": "Pro edition"
},
{
"F": "Smart Phone",
"D": "Quad core"
}
]
}
]

PHP json_encode creates number index as string instead of an object

I have the following example code in PHP:
$data = array(
'hello',
'world',
'hi'
);
$ret = array();
$ret['test'] = array();
$ret['testing'] = array();
foreach($data as $index => $value){
if($index < 1){
$ret['test'][$index]['val'] = $value;
$ret['test'][$index]['me'] = 'index < 1';
}
else {
$ret['testing'][$index]['val'] = $value;
$ret['testing'][$index]['me'] = 'index >= 1';
}
}
echo json_encode($ret);
I would expect this to be the JSON output:
[{
"test":[
{
"val": "hello",
"me": "index < 1"
}
],
"testing":[
{
"val": "world",
"me": "index >= 1"
},
{
"val": "hi",
"me": "index >= 1"
}
]
}]
However, what ends up happening is that I end up with the following:
[{
"test":[
{
"val": "hello",
"me": "index < 1"
}
],
"testing":{
"1":{
"val": "world",
"me": "index >= 1"
},
"2":{
"val": "hi",
"me": "index >= 1"
}
}
}]
The "1" and "2" keys appear despite being an int and despite the correct rendering of test when the same counter variable is used. Is there a way I can make sure that testing becomes an array of JSON objects?
Because the array doesn't start with index 0 but with index 1, it's encoded as an JSON object instead of an JSON array.
You can use the array_values() function to remove the indexes and only keep the values.
Example:
$ret['testing'] = array_values($ret['testing'])
echo json_encode($ret);
But because you don't need the index at this moment, you can also refactor your code to this:
foreach($data as $index => $value){
if($index < 1){
$ret['test'][] = array(
'val' => $value,
'me' => 'index < 1'
);
}
else {
$ret['testing'][] = array(
'val' => $value,
'me' => 'index >= 1'
);
}
}
echo json_encode($ret);
This way, the arrays will always start with index 0.

Trying create an associative array?

I have an array
Array
(
[0] => Array
(
[NT_NOTAFINAL] => 10.00
[M_DESCRICAO] => ARTE
[PE_DESCRICAO] => 1 BIMESTRE
)
[1] => Array
(
[NT_NOTAFINAL] => 10.00
[M_DESCRICAO] => ARTE
[PE_DESCRICAO] => 2 BIMESTRE
)
[2] => Array
(
[NT_NOTAFINAL] => 10.00
[M_DESCRICAO] => ARTE
[PE_DESCRICAO] =>3 BIMESTRE
)
)
Now I'm trying create an associative array to return JSON something like this:
"Materia":[{"descricao":"ARTE", "Notas":["1 BIMESTRE":10.00, "2 BIMESTRE":10.00, "3 BIMESTRE":10.00]}]
I don't know how I could create this associative array to this JSON result from this array that I'm posting.
I'm trying create like this but the result what I need does not return
$notas = '';
$materia = '';
foreach($lista as $value){
if($value["M_DESCRICAO"] != $materia){
$materia = $value["M_DESCRICAO"];
}
$notas = array("Descricao"=>$materia, "Notas"=>array($value["PE_DESCRICAO"]=>$value["NT_NOTAFINAL"]));
}
$result = array("Materia"=>array($notas));
echo json_encode($result);
The result to what I'm trying is
{
"Materia": [
{
"Descricao": "ARTE",
"Notas": {
"3 BIMESTRE": "10.00"
}
}
]
}
How could I create this associative array to return this JSON like I need ?
Edit
$notas = array();
$materia = '';
$materia_array = array();
foreach($lista as $value){
if($materia == ''){
$materia = $value["M_DESCRICAO"];
}
if($value["M_DESCRICAO"] != $materia){
array_push($materia_array, (array("Descricao"=>$materia,"Notas"=>$notas)));
$notas = array();
$materia = $value["M_DESCRICAO"];
}else{
array_push($notas, array($value["PE_DESCRICAO"]=>$value["NT_NOTAFINAL"]));
}
}
$result = array("Materia"=>$materia_array);
echo json_encode($result);
Result
{
"Materia": [
{
"Descricao": "ARTE",
"Notas": [
{
"1 BIMESTRE": "10.00"
},
{
"2 BIMESTRE": "10.00"
},
{
"3 BIMESTRE": "10.00"
}
]
},
{
"Descricao": "C.SOCIAIS",
"Notas": [
{
"2 BIMESTRE": "10.00"
},
{
"3 BIMESTRE": "9.50"
}
]
},
{
"Descricao": "CIƊNCIAS E P. S.",
"Notas": [
{
"2 BIMESTRE": "9.50"
},
{
"3 BIMESTRE": "10.00"
}
]
}
]
}
I've refactored your last edit to remove some code duplication and complexity.
$result = array();
foreach ($lista as $value) {
$materia = $value['M_DESCRICAO'];
if (!isset($result[$materia])) {
$result[$materia] = array(
'Descricao' => $materia,
'Notas' => array()
);
}
$result[$materia]['Notas'][] = array(
$value['PE_DESCRICAO'] => $value['NT_NOTAFINAL']
);
}
$result = array('Materia' => array_values($result));
echo json_encode($result);
In addition to my comment, this would be the code to push all notes to an array as long as the M_DESCRICAO does not change, so the starting array $lista needs to be ordered first. Is this what you were after (code is not tested, office computer :-))?
$notas = $materia = null;
$result = $tmp = array();
$len = count($lista);
for ($i=0;$i<$len;$i++) {
$notas = array();
$materia = $lista[$i]["M_DESCRICAO"];
while (($materia == $lista[$i+1]["M_DESCRICAO"]) && ($i < ($len -1))) {
$notas[$lista[$i]["PE_DESCRICAO"]] = $lista[$i]["NT_NOTAFINAL"];
$i++;
}
// now $notas holds all corresponding entries
$tmp[] = array("Descricao"=>$materia, "Notas" => $notas);
}
$result = array("Materia"=>array($tmp));
echo json_encode($result);
I worked out an untested (there might be some errors, but logically it should work) piece of code, but it might help you:
$notas;
$materia = '';
$materia_array;
foreach($lista as $value){
if($materia == '')
$materia = $value["M_DESCRICAO"];
if($value["M_DESCRICAO"] != $materia){
array_push($materia_array, (array("Descricao"=>$materia,"Notas"=>$notas));
unset($notas); //<--------
$notas = array();//<--------
$materia = $value["M_DESCRICAO"];
}
else
{
array_push($notas, array($value["PE_DESCRICAO"]=>$value["NT_NOTAFINAL"]))
}
}
$result = array("Materia"=>$materia_array);
echo json_encode($result);
This should work for multiple M_DESCRICAO values

PHP Comprehensive Object Difference Function

Does anyone know of a php function that will take in two objects and return a complete set of differences back as an object?
I'll use json encoded data as an example of what I'm trying to accomplish:
Object A:
{
"Name":"Original",
"Id": 5,
"Data":{
"Value1": 1,
"Value2": [
5, 7, 8, 10
],
"Value3": {
"Exists": true
}
}
}
Object B:
{
"Name":"ThisNameChanged",
"Id": 5,
"Data":{
"Value1": 7,
"Value2": [
5, 8, 9
],
"Value3": {
"Exists": true
}
}
}
Would return:
{
"Name":"ThisNameChanged",
"Data":{
"Value2": {
"1": 8,
"2": 9
}
}
}
If no such function exists (which I guess is likely), how might I write a function to do this? Would anyone be able to provide an example, or the function?
Here is some simple example of function you ask for,
but it is not perfect, just food for thought for you:
function objDiff ($obj1, $obj2) {
$diff=array();
$obj1Arr = (array)$obj1;
$obj2Arr = (array)$obj2;
foreach ($obj1Arr as $key=>$val) {
if (!(isset($obj2Arr[$key]) && $obj2Arr[$key]===$val )) {
if (gettype($val)=='object') {
if (isset($obj2Arr[$key])) {
if (gettype($obj2Arr[$key])=='object') {
$subDiff = objDiff($val,$obj2Arr[$key]);
$diff[$key]=$subDiff;
} else {
$diff[$key]=array($val,$obj2Arr[$key]);
}
} else {
$diff[$key]=array($val,$obj2Arr[$key]);
}
} else {
$diff[$key]=array($val,(isset($obj2Arr[$key]))?$obj2Arr[$key]:null);
}
}
}
return $diff;
}
with this data:
$obj1 = new stdClass();
$obj1->test1 = 1;
$obj1->test2 = 2;
$subObj = new stdClass();
$subObj->test1 = 1;
$subObj->test2 = 2;
$obj1->test3 = $subObj;
$obj2 = new stdClass();
$obj2->test1 = 3;
$obj2->test2 = 4;
$subObj = new stdClass();
$subObj->test1 = 3;
$subObj->test2 = 2;
$obj2->test3 = $subObj;
print_r(objDiff($obj1,$obj2) );
it returns:
Array
(
[test1] => Array
(
[0] => 1
[1] => 3
)
[test2] => Array
(
[0] => 2
[1] => 4
)
[test3] => Array
(
[test1] => Array
(
[0] => 1
[1] => 3
)
)
)
Thanks to Kim Alexander, I was able to write a code that accomplished what I was looking to do.
function objDiff($obj1, $obj2, $diff = null) {
if (is_null($diff))
$diff = new stdClass;
$obj1Arr = (array)$obj1;
$obj2Arr = (array)$obj2;
foreach($obj1Arr as $key => $val) {
if (isset($obj2Arr[$key]))
{
if ($obj2Arr[$key] != $val)
{
if (is_object($obj2Arr[$key]) && is_object($val))
$diff->$key = objDiff($val, $obj2Arr[$key]);
else
$diff->$key = $obj2Arr[$key];
}
}
}
return $diff;
}

Recursivly search array and sum field

I am trying to write a recursive function that will iterate over an array of arrays and sum a specific field. Here is an example of an array:
{
"68": {
"10": [
{
"id": "3333",
"sumTHis": "5"
}
]
},
"69": {
"45": [
{
"id": "3333",
"sumTHis": "5"
}
],
"50": [
{
"id": "3330",
"sumTHis": "5"
},
{
"id": "3331",
"sumTHis": "5"
},
{
"id": "3332",
"sumTHis": "5"
},
{
"id": "3333",
"sumTHis": "5"
}
]
}
}
The problem is that the array could be any number of sub-arrays deep. In the end, I would like to be able to sum all "sumTHis" nodes throughout the entire array The code I have so far is this:
//in body
$sumThis= recurse_get_total($array, 'sumTHis');
//recursive function
function recurse_get_total($report_data, $valId, $total = 0){
try{
foreach ($report_data as $key => $value) {
if(is_array_of_arrays($value)){
recurse_get_total($value, $valId, $total);
}else{
$total = $total + $value[$valId];
return $total;
}
}
return $total;
}catch(Exception $err){
throw $err;
}
}
function is_array_of_arrays($isArray){
try{
if(is_array($isArray)){
foreach($isArray as $key => $value){
if(!is_array($value)){
return false;
}
}
return true;
}
}catch(Exception $err){
throw $err;
}
}
This function starts to iterate over the array but gets kicked out after the first one and returns 0. Can anyone help out?
Thanks
jason
Going about this problem I set something up with "array_walk_recursive". Seeing that you want to add some stuff independent of the depth of the arrays, this seems to work.
It is not solving it with what you have, but perhaps this different approach will get you there.
$sum = 0;
$array = array(
"one" => array(
"day" => "tuesday",
"week" => "20",
"findthis" => 10
),
"two" => array("subone" => array(
"some" => "one",
"findthis" => 23
)),
"deeperthree" => array("subtwo" => array("deeper" => array(
"one" => "entry",
"findthis" => 44
)))
);
function callback($val, $key, $arg) {
if ($key == "findthis") {
$arg[0]($val, $arg[1]);
}
};
$function = function($num, &$sum) {
$sum = $sum + $num;
echo $sum . " ";
};
array_walk_recursive($array, "callback", array( $function, &$sum ));
result: 10 33 77

Categories