How to fetch JSON array in Retrofit? - php

I have a JSON array inside which there are JSON Objects like this:
[
{
"id": "63",
"userprofile": "userprofile.jpg",
"username": "James",
"content": "test.",
"address": "1111 Parker St",
"Post_date": "2022-05-25 02:41:15",
"images": [
"20220525_0241291.jpg",
"20220525_0241290.jpg"
]
}
]
I would like to have the string elements in the images array as objects instead. Can anyone suggest me how to make this type of JSON?
[
{
"id": "63",
"userprofile": "userprofile.jpg",
"username": "James",
"content": "test.",
"address": "1111 Parker St",
"Post_date": "2022-05-25 02:41:15",
"images": [
{"image": "20220525_0241291.jpg"},
{"image": "20220525_0241290.jpg"}
]
}
]
Here is my PHP code
<?php
header("Content-Type:application/json");
include '../db_con.php';
$query = "SELECT Board.* ,
GROUP_CONCAT(Board_images.imagepath separator ',') AS multiimages
FROM Board
LEFT JOIN Board_images ON Board.index = Board_images.boardindex
GROUP BY Board.index
ORDER BY Board.index";
$result = mysqli_query($conn, $query);
$response = array();
while ($row = mysqli_fetch_assoc($result)) {
array_push(
$response,
array(
'id' => $row['index'],
'userprofile' => $row['userprofile'],
'username' => $row['username'],
'content' => $row['content'],
'address' => $row['address'],
'Post_date' => $row['Post_date'],
'images' => explode(',',$row['multiimages'])
)
);
}
echo json_encode($response);
?>

explode returns a simple array of strings. All you have to do is go over it and put each of those strings into an array. You can do this in a loop or using an array function like array_map() which will do the same thing, applying a callback to each item.
You also don't need a loop to populate your response array, instead use mysqli_result::fetch_all(). You could use a loop to add the extra images element, but again I prefer using the array_walk() function as a matter of personal opinion.
(The difference between array_map and array_walk is that array_map returns a new array based on what the callback returns. array_walk only modifies the existing array.)
<?php
include '../db_con.php';
$query = "SELECT Board.* , GROUP_CONCAT(Board_images.imagepath separator ',') AS multiimages FROM Board
LEFT JOIN Board_images ON Board.index = Board_images.boardindex GROUP BY Board.index ORDER BY Board.index";
$result = $con->query($query);
// fetch all the records at once
$response = $result->fetch_all(\MYSQLI_ASSOC);
// this performs similar function to a foreach loop
array_walk(
$response,
function (&$v, $k) {
// explode the comma-separated list into an indexed array
$images = explode(",", $v["multiimages"]);
// now turn it into a bunch of associative arrays
$images = array_map(fn ($im) => ["image" => $im], $images);
// and then add it to the original $response array
$v["images"] = $images;
}
);
header("Content-Type:application/json");
echo json_encode($response);

Related

Encode multidimensional array using while loop

I have a multidimensional array and I want it printed like these by using PHP, but there is no comma separating the curly braces }{ and it should be like },{. Can you guys help me?
{"user_activity": [{
"log_number": "1",
"log_user_1": "w120511891",
"log_activity_id": "A0002DOC",
"log_user_2": "",
"log_document_id": "DSX00012",
"log_material_id": "",
"log_timestamp": "2021-10-23 13:52:35",
"log_rand_key": "127",
"log_hash_key": "09c7e3bb5d6f74c257aa4b4cdae388a69177c7dc",
"log_project_id": "1520002",
"log_number_reference": "",
"log_close": "1"
}{
"log_number": "9",
"log_user_1": "W201005911",
"log_activity_id": "A0004DOC",
"log_user_2": "",
"log_document_id": "DSX00012",
"log_material_id": "",
"log_timestamp": "2021-10-25 10:35:29",
"log_rand_key": "127",
"log_hash_key": "d04e8d1ef5c9f8b85a3f7556b92d6a7fcdc11639",
"log_project_id": "1520002",
"log_number_reference": "1",
"log_close": "1"
}]}
This is my PHP Code
echo "{\"user_activity\": [";
while($rsel_userAct_p = mysqli_fetch_array($xsel_userAct_p, MYSQLI_ASSOC)) {
print_r(json_encode($rsel_userAct_p), JSON_PRETTY_PRINT);
}
echo "]}";
You're doing it wrong. Just create an array, append data from MySQL into it and json_encode the array itself:
$array = [];
while ($rsel_userAct_p = mysqli_fetch_array($xsel_userAct_p, MYSQLI_ASSOC)) {
$array["user_activity"][] = $rsel_userAct_p;
}
echo json_encode($array, JSON_PRETTY_PRINT);
Or even better:
$array = [
"user_activity" => mysqli_fetch_all($xsel_userAct_p, MYSQLI_ASSOC)
];
echo json_encode($array, JSON_PRETTY_PRINT);
Your issue is that you are using print_r in the first place. print_r is meant to print out a very specific format which helps with array structures but has nothing to do with json.
Taken from the print_r documentation
<pre>
<?php
$a = array ('a' => 'apple', 'b' => 'banana', 'c' => array ('x', 'y', 'z'));
print_r ($a);
?>
</pre>
will result in
Array
(
[a] => apple
[b] => banana
[c] => Array
(
[0] => x
1 => y
[2] => z
)
)
What you actually want (at least guessing from your code example) is you want to print out a single json object that consists of multiple results from your database, based upon the array result you got before.
So instead of using your current code, you create a proper array structure in the first place and then you print it out with the given json function.
$activities = [
'user_activity' => []
];
while($rsel_userAct_p = mysqli_fetch_array($xsel_userAct_p, MYSQLI_ASSOC)) {
$activities['user_activity'][] = $rsel_userAct_p;
}
echo json_encode($activities, JSON_PRETTY_PRINT);
The actual result should look exactly like you intend the result to be, and even works regardless of the amount of entries in your database.
This will make your JSON in correct format:
$json='{"user_activity": [{
"log_number": "1",
"log_user_1": "w120511891",
"log_activity_id": "A0002DOC",
"log_user_2": "",
"log_document_id": "DSX00012",
"log_material_id": "",
"log_timestamp": "2021-10-23 13:52:35",
"log_rand_key": "127",
"log_hash_key": "09c7e3bb5d6f74c257aa4b4cdae388a69177c7dc",
"log_project_id": "1520002",
"log_number_reference": "",
"log_close": "1"
}{
"log_number": "9",
"log_user_1": "W201005911",
"log_activity_id": "A0004DOC",
"log_user_2": "",
"log_document_id": "DSX00012",
"log_material_id": "",
"log_timestamp": "2021-10-25 10:35:29",
"log_rand_key": "127",
"log_hash_key": "d04e8d1ef5c9f8b85a3f7556b92d6a7fcdc11639",
"log_project_id": "1520002",
"log_number_reference": "1",
"log_close": "1"
}]}';
$json=str_replace("}{","},{",$json);
Then you can use :
echo "<pre>";
print_R(json_decode($json,true));
to convert JSON to PHP array.
You can use in while like:
$json = [];
while ($rsel_userAct_p = mysqli_fetch_array($xsel_userAct_p, MYSQLI_ASSOC)) {
$json["user_activity"][] = $rsel_userAct_p;
}
echo json_encode($json, JSON_PRETTY_PRINT);

Array_Diff is deleting only the key/value from the array of objects but not the whole object

I have a script that ultimately produces a JSON array. Producing the JSON array works fine, with the exception that I can't seem to delete an entire object from an array of objects when searching for a specific keys value.
Producing the Array:
$sql="SELECT * FROM `emails` WHERE `subject` LIKE '%5678%' order by `id` DESC LIMIT 50";
$result = mysqli_query($DatabasePointer2,$sql) or die(mysqli_error($DatabasePointer2));
$row_cnt = mysqli_num_rows($result);
if($row_cnt>0) {
$array = array();
$i=0;
while($row = mysqli_fetch_array($result)) {
$i++;
$a1 = explode('-', $row['body']);
$a1[0] = str_replace("","",$a1[0]);
$a1[1] = str_replace("TF: ","",$a1[1]);
$a1[1] = str_replace("minutes","M",$a1[1]);
$a = array(
"p" => "test",
"id" => $row['id'],
"thekey" => $a1[1],
"time" => $dt->format('Y-m-d H:i:s'),
"utctime" => strtotime($dt->format('Y-m-d H:i:s')),
"utc2" => $two->format('Y-m-d H:i:s'),
"utc3" => $three->format('Y-m-d H:i:s')
);
$a1 = array_diff($a, ["keytoexclude1", "keytoexclude2", "keytoexclude3"]);
$array[] = $a1;
}
}
echo json_encode($array, JSON_UNESCAPED_SLASHES);
Note that value of thekey is not static.
The code above, produces this:
[{
"p": "test",
"id": "198645",
"time": "2020-05-06 23:00:49",
"utctime": 1588806049,
"utc2": "2020-05-07 01:00:49",
"utc3": "2020-05-07 02:00:49"
}, {
"p": "test",
"id": "198605",
"time": "2020-05-06 22:00:55",
"utctime": 1588802455,
"utc2": "2020-05-07 00:00:55",
"utc3": "2020-05-07 01:00:55",
"thekey": "123456"
}, {
"p": "test",
"id": "198604",
"time": "2020-05-06 22:00:54",
"utctime": 1588802454,
"utc2": "2020-05-07 00:00:54",
"utc3": "2020-05-07 01:00:54"
}]
What I'm trying to accomplish is to search for any key that matches a list of exclusions, and then remove the whole object if it finds a key in the list of exclusions.
List of Exclusions/Code to remove...
$a1 = array_diff($a, ["keytoexclude1", "keytoexclude2", "keytoexclude3"]);
Whats happening, is that it just removes the key/value itself, but keeps the rest of the object.
If you look in the array above, you'll see that if an exclusion was found, it only removes "thekey" and its value from the object, but leaves the rest of the keys in the objects.
Can somebody please assist in how to remove the whole object?
**Updated to show mistake where the value for "thekey" isn't supposed to come from the mysql database, but the exploded array.
Use an if statement to check if the value is in the list of exclusions, and skip the row.
while($row = mysqli_fetch_array($result)) {
if (in_array($row['thevalue'], ["keytoexclude1", "keytoexclude2", "keytoexclude3"])) {
continue;
}
$a = array(
"p" => "test",
"id" => $row['id'],
"thekey" => $row['thevalue'],
"time" => $dt->format('Y-m-d H:i:s'),
"utctime" => strtotime($dt->format('Y-m-d H:i:s')),
"utc2" => $two->format('Y-m-d H:i:s'),
"utc3" => $three->format('Y-m-d H:i:s')
);
$array[] = $a1;
}

PHP - Find an object by key in an array of objects, update its value

I have an array of objects, and want to update an attribute of one of the objects.
$objs = [
['value' => 2, 'key' => 'a'],
['value' => 3, 'key' => 'b'] ,
];
Let's say I want to set the 'value' of the object with 'key'=>'a' to 5.
Aside from iterating over the array searching for the key, is there any quicker/efficient way of doing this?
Thanks.
EDIT: There is debate as to why I can't use an associative array. It is because this array is obtained from a JSON value.
If my JSON object is this:
"obj": {
"a": {
"key": "a",
"value": 2
},
"b": {
"key": "b",
"value": 3
}
}
There is no guarantee that the order of the objects will be retained, which is required.
Hence I need an index in each object to be able to sort it using usort(). So my JSON needs to be:
"obj": {
"a": {
"key": "a",
"value": 2,
"index": 1
},
"b": {
"key": "b",
"value": 3,
"index": 2
}
}
But I cannot use usort() on an object, only on arrays. So my JSON needs to be
"obj": [
{
"key": "a",
"value": 2,
"index": 1
}, {
"key": "b",
"value": 3,
"index":2
}
]
Which brings us to the original question.
By using array_column(), you can pull all the values with the index key in the arrays. Then you can find the first occurrence of the value a by using array_search(). This will only return the first index where it finds a value. Then you can simply replace that value, as you now have the index of that value.
$keys = array_column($objs, 'key');
$index = array_search('a', $keys);
if ($index !== false) {
$objs[$index]['value'] = 5;
}
See this live demo.
http://php.net/array_search
http://php.net/array_column
You can make the array associative with array column. That way you can directly assign the value.
$objs = [ ['value'=>2, 'key'=>'a'], ['value'=>3, 'key'=>'b'] ];
$objs = array_column($objs, null, "key");
$objs['a']['value'] = 5;
https://3v4l.org/7tJl0
I want to recommend you reorginize your array lake that:
$objs = [
'a' => ['value'=>2, 'key'=>'a'],
'b' => ['value'=>3, 'key'=>'b']
];
And now
if( array_key_exists( 'a', $objs )) {
$objs ['a'] ['value'] = 5;
}
I had it like that initially. But I need for the objects to have an
index value in them, so I can run usort() on the main array. This is
because the array comes from JSON where the original order isn't
respected
Then create an index array:
// When fill `$objs` array
$objs = [];
$arrIndex = [];
$idx = 0;
foreach( $json as $item ) {
$arrIndex [ $item ['key']] = $idx;
$objs [$idx ++] = $item;
}
// And your task:
if( array_key_exists( 'a', $arrIndex )) {
$objs [ $arrIndex ['a']] ['value'] = 5;
}
Aside from iterating over the array searching for the key, is there
any quicker/efficient way of doing this?
You have to pay the price of iteration either way.
You can search your collection for the interesting object (takes linear time), or you form some kind of dictionary data structure, e.g. hash table (takes linear time) and then find the interesting object in constant time.
No free lunches here.

Change ID of returned array

I have the following method:
$results = array_filter($arr['people'], function($people) use ($searchId) {
return in_array($searchId, $people['member']);
});
echo json_encode($results);
This returnes an array like this:
[{"id":"8080","content":"foo","member":[123,456],"interval":7}]
But if there more than one result it will return this:
["0": {"id":"8080","content":"foo","member":[123,456],"interval":7}]
["5": {"id":"8082","content":"bar","member":[1234,3456],"interval":5}]
I want to replace the "automatically" given ID with the ID which is in the Array - like this:
["8080": {"id":"8080","content":"foo","member":[123,456],"interval":7}]
["8082": {"id":"8082","content":"bar","member":[1234,3456],"interval":5}]
Have somebody an idea?
Try this one,
$arr = [
0 => [
"id" => 8082,
"content" => "test",
"interval" => "7",
],
5 => [
"id" => 8086,
"content" => "test",
"interval" => "7",
],
];
$ids = array_column($arr, "id");
$result = array_combine($ids, $arr);
print_r($result);
echo json_encode($result);
array_column which states Return the values from a single column in the input array.
array_combine which states Creates an array by using one array for keys and another for its values.
Try this simple way :
$arr[$newkey] = $arr[$oldkey];
unset($arr[$oldkey]);

Append JSON Data to JSON File Located on Server with PHP

I have a JSON file stored on my server that I need to add data to. I have successfully retrieved the file into memory and have parsed it successfully. I am just having a hard time placing the new JSON data in the correct spot.
Here is the format of my JSON file:
{
"emails": [
{
"group": "1st Group",
"list": [
{
"id": 1,
"subject": "Testing 1"
},
{
"id": 2,
"subject": "Testing 2"
}
] // End list array
}, // End 1st Group
{
"group": "2nd Group",
"list": [
{
"id": 3,
"subject": "Testing 3"
},
{
"id": 4,
"subject": "Testing 4"
}
] // End list array
} // End 2nd Group
/* NEED TO INSERT NEW DATA HERE */
] // End emails array
}
I am trying to append a new group list after the last group list. In this example, that would be after this line: } // End 2nd Group.
Here is my PHP code which gets the JSON file from my server and parses it:
$getJSON = file_get_contents('emails.json');
$tempArray = json_decode($getJSON, true);
$numberOfGroups = count($tempArray['emails'][0]);
And here is my php code that creates the format/layout of my JSON file:
$groupArray = array();
$json = array( 'emails' => array() );
foreach ($contextIORequest->getData() as $message) {
$newTZ = new DateTimeZone("America/Chicago");
$currentTime = new DateTime();
$currentTime = DateTime::createFromFormat('U', $message['date_received']);
$currentTime->setTimezone($newTZ);
$formattedDateReceived = $currentTime->format('F j, Y');
if (!in_array($formattedDateReceived, $groupArray)) {
array_push( $json['emails'],
array(
'group' => $formattedDateReceived,
'list' => array()
)
);
$groupArray[] = $formattedDateReceived;
}
$body = str_replace(array("\r\n","\n"),"", $message['body'][0]['content']);
$newBody = preg_replace('!\s+!', ' ', $body);
array_push($json['emails'][array_search($formattedDateReceived,$groupArray)]['list'],
array(
'id' => $message['message_id'],
'subject'=> addslashes($message['subject']),
'to' => array("Me"),
'body' => $newBody,
'time' => $formattedDateReceived,
'datetime' => $formattedDateReceived,
'from' => $message['addresses']['from']['name'],
'dp' => "assets/img/profiles/avatar.jpg",
'dpRetina' => "assets/img/profiles/avatar2x.jpg"
)
);
} // end foreach loop
// Output the JSON
header('Content-Type: application/json');
echo json_encode($json);
So how would I go about appending a new group list after the last group list? And this needs to be done without actually included the emails array used to create the JSON.
After running json_decode on the serialized data (with the second param passed as true like you've done), you'll have, in PHP, an associative array which has one element at a key named emails. That element is an array and holds the group lists to which you want to add another. So it's a matter of:
$data = json_decode($getJSON, true);
$data['emails'][] = $TheNewGroupList;
Don't let the fact that it started as serialized data in JSON format get you frazzled. Once you've run json_decode it's just a PHP data structure (object or array), and operations on it are just like any other PHP data.

Categories