Extract key value pair output from JSON file using PHP - php

I would like to extract key value pair output from JSON formatted file using PHP and put into html table & database with exact key column. I tried code mentioned in Extract JSON ouput to get line by line key pair values using PHP but it doesn't work for multiple lines and gives wrong output from 2nd line onwards itself due to multiple lines from 2nd key.
As we discussed in that, filing separate question to avoid clutter the same question.
JSON file content:
{"key":"SEM-5765","status":"Closed","components":"UX","affectedVersions":"SEM 8.8.x","fixVersions":"SurmaZuse-8.8.10","customerFacingInfo":"[https://goog.ezy.com/show_bug.cgi?id=109021 Bug 109021] - Content spoofing (text) via loginErrorCode \[CWE-345\]"} {"key":"SEM-3325","status":"Closed","components":"UX","affectedVersions":"SEM Prior to 8.7","fixVersions":"SurmaZuse-8.8.10","customerFacingInfo":"Fixed a number of bugs related to Delegated Admin in the Admin Console:
* \"New administrator\" creation button was not disabled for delegated admin without required rights ([https://goog.ezy.com/show_bug.cgi?id=108503 Bug 108503])
* \"Account Limits\" in domain settings could not be shown even when adminConsoleDomainLimitsTabRights was added ([https://goog.ezy.com/show_bug.cgi?id=108327 Bug 108327])
* Had been unable to remove \"Dynamic Group\" from distribution properties page ([https://goog.ezy.com/show_bug.cgi?id=108499 Bug 108499])
* After performing a bulk migration, the Delegated Admin user encountered an `HTTP Error 403` when attempting to download the list of provisioned accounts ([https://goog.ezy.com/show_bug.cgi?id=108539 Bug 108539])"} {"key":"SEM-2755","status":"Closed","components":"UX","affectedVersions":"SEM Prior to 8.7","fixVersions":"SurmaZuse-8.8.10","customerFacingInfo":"Global Admin can now control the Downloads View (Admin > Tools > Download) and Help Center view for Delegated Admins."}
Expected:
SEM-5765
Closed
UX
SEM 8.8.x
SurmaZuse-8.8.10
[https://goog.ezy.com/show_bug.cgi?id=109021 Bug 109021] - Content spoofing (text) via loginErrorCode \[CWE-345\]
SEM-3325
Closed
UX
SEM Prior to 8.7
SurmaZuse-8.8.10
Fixed a number of bugs related to Delegated Admin in the Admin Console: * \"New administrator\" creation button was not disabled for delegated admin without required rights ([https://goog.ezy.com/show_bug.cgi?id=108503 Bug 108503]) * \"Account Limits\" in domain settings could not be shown even when adminConsoleDomainLimitsTabRights was added ([https://goog.ezy.com/show_bug.cgi?id=108327 Bug 108327]) * Had been unable to remove \"Dynamic Group\" from distribution properties page ([https://goog.ezy.com/show_bug.cgi?id=108499 Bug 108499]) * After performing a bulk migration, the Delegated Admin user encountered an `HTTP Error 403` when attempting to download the list of provisioned accounts ([https://goog.ezy.com/show_bug.cgi?id=108539 Bug 108539])
SEM-2755
Closed
UX
SEM Prior to 8.7
SurmaZuse-8.8.10
Global Admin can now control the Downloads View (Admin > Tools > Download) and Help Center view for Delegated Admins.
Tried code:
echo "<table class='table create-release-note-table'>
<thead>
<tr><th>#</th><th>Ticket ID</th><th>Status</th><th>Components</th><th>Affected Versions</th><th>Fix Versions</th><th>Description</th></tr>
</thead>
<tbody>";
$i = 0;
$resultFile = fopen($resultURL, "r");
#$lines = file($resultURL, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
#print_r ($lines);
#exit;
while (!feof($resultFile)) {
$line = trim(fgets ($resultFile));
$line = str_replace("\\\"", "", $line);
$line = stripslashes($line);
$lineArray = json_decode($line, true);
echo "<tr><td>" . ++$i . "</td>";
parseData($lineArray);
echo "</tr>";
}
echo "</tbody></table>";
fclose ($resultFile);
// Parse release note data
function parseData($array) {
$value = str_replace(",", ";", $value);
foreach ($array as $key => $value) {
if (is_bool($value)) {
echo ("<td>" . $value? 'true' : '') . "</td>";
} else {
echo "<td>" . $value . "</td>";
}
}
}

Your JSON seems not be formatted well in first place. You missed commas and square brackets.
This is a very basic solution but you can correct your JSON following this method:
Add commas
$json = str_replace("} {", "}, {", $original_json);
Clean a bit the code (this is rough. Good for your case but not the best at all!)
$json = str_replace("\[", "[", $json);
$json = str_replace("\]", "]", $json);
Wrap it inside [ ]
$your_json_string = "[" . $json . "]";
and then you can just use
$json_parsed = json_decode($your_json_string);
and
echo "<table class='table create-release-note-table'>
<thead>
<tr>
<th>#</th>
<th>Ticket ID</th>
<th>Status</th>
<th>Components</th>
<th>Affected Versions</th>
<th>Fix Versions</th>
<th>Description</th>
</tr>
</thead>
<tbody>";
foreach($json_parsed as $json_object){
echo "<tr>";
echo "<td></td>";
echo "<td>" . $json_object->key . "</td>";
echo "<td>" . $json_object->status. "</td>";
echo "<td>" . $json_object->components. "</td>";
echo "<td>" . $json_object->affectedVersions. "</td>";
echo "<td>" . $json_object->fixVersions . "</td>";
echo "<td>" . $json_object->customerFacingInfo . "</td>";
echo "</tr>";
}
echo "</tbody>
</table>";
That's it

I'm afraid the issue is on the json file side.
If I understand correctly, the JSON file content exposed in your question is supposed to be a single json file.
If so, the format of the json seems incorrect.
Your json is structured as follow (I remove some parts of the content to help clarify my point):
{"key":"SEM-5765"}
{"key":"SEM-3325"}
{"key":"SEM-2755"}
Which is not a single json, but 3 differents jsons on a single file.
A correct json structure would have been:
[
{"key":"SEM-5765"},
{"key":"SEM-3325"},
{"key":"SEM-2755"},
]
Which is an array of json and a correct json structure.
So I think you have two possibilities :
you can correct the json structure
you can read your file by separating each line and traited each line as a single json
Either way, you will have to add a step to your code to loop through each line/json entity

In your case you can use explode and implode php function to get your desire output.
I have added few code lines :
$lineExplode = explode('}',$line);
$line = implode(',',$lineExplode);
$lineArray = json_decode("[".$line."]", true);
All other code is the same as your example:
<?php
echo "<table class='table create-release-note-table'>
<thead>
<tr><th>#</th><th>Ticket ID</th><th>Status</th><th>Components</th><th>Affected Versions</th><th>Fix Versions</th><th>Description</th></tr>
</thead>
<tbody>";
$i = 0;
$resultFile = fopen($resultURL, "r");
#$lines = file($resultURL, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
#print_r ($lines);
#exit;
while (!feof($resultFile)) {
$line = trim(fgets ($resultFile));
$line = str_replace("\\\"", "", $line);
$line = stripslashes($line);
$lineExplode = explode('}',$line);
$line = implode(',',$lineExplode);
$lineArray = json_decode("[".$line."]", true);
echo "<tr><td>" . ++$i . "</td>";
parseData($lineArray);
echo "</tr>";
}
echo "</tbody></table>";
fclose ($resultFile);
// Parse release note data
function parseData($array) {
$value = str_replace(",", ";", $value);
foreach ($array as $key => $value) {
if (is_bool($value)) {
echo ("<td>" . $value? 'true' : '') . "</td>";
} else {
echo "<td>" . $value . "</td>";
}
}
}
?>

Related

Create a bidimensional array in php

I confess that I am a beginner. My goal is to be able to summarize in a two-dimensional table the amount per month (in column) for each class (in line). After doing a lot of research, I arrived at this stage in my project.
My problem is , I get the result with months repeating in columns like here.
Here is my code.
This is my sql code : "SELECT classe, mois, sum_ec FROM journal"
This is my php code :
<?php
$tableau = array();
$tblClasse = array();
$rt = mysqli_query($db, $req_sit);//execute la requete
while ($row = $rt->fetch_assoc()){ //forme le tableau
$tableau[$row['classe']][$row['mois']] = $row['sum_ec'];
if (!in_array($row['classe'],$tblClasse)) {
$tblClasse[] = $row['mois'];
}
}
echo '<table border="1">
<tr>
<th> </th>';
foreach ($tblClasse as $classe) {
echo '<th>' . htmlspecialchars($classe) . '</th>';
}
echo '</tr>';
foreach ($tableau as $mois=>$value) {
echo '<tr>';
$new_line = TRUE;
foreach ($tblClasse as $classe) {
if ($new_line) {
echo '<td>' . $mois . '</td>';
$new_line = FALSE;
}
$display = isset($value[$classe]) ? $value[$classe] : " ";
echo '<td>' . $display . '</td>';
}
echo '</tr>';
}
?>
Can someone tell me what mistake I made?
The problem is in this part of your code:
if (!in_array($row['classe'],$tblClasse)) {
$tblClasse[] = $row['mois'];
}
You are adding months (Fev, Mar) to the array and trying to check if it contains classes (PS, MS etc.) which is impossible, and this condition always returns true, so Feb is added to the $tblClasse array at each iteration. You must either check months or classes and add months or classes to the array respectively. And if you want the array to contain unique values (for example, months), use keys instead of values:
if (!array_key_exists ($row['mois'],$tblClasse)) {
$tblClasse[$row['mois']] = 1;
}
Where 1 can be replaced with any other value.
In the further part of your code use the keys, not values of $tblClasse array to form the table heading.
foreach (array_keys ($tblClasse) as $mois) {
echo '<th>' . htmlspecialchars($mois) . '</th>';
}
Eureka! It worked. I just had to change the line for the values ​​to "array_keys"
foreach (array_keys($tblClasse) as $classe) {
if ($new_line) {
echo '<td>' . $mois . '</td>';
$new_line = FALSE;
}
as well and boom! It's perfect. Thank you very much my dear. You have given me a lot of happiness.

Creating a PHP Page to Search a CSV

I have a CSV that is appended every 10 minutes with Data that looks similar to
07-01-2020 10:40 https://www.google.com OK 0.080382
07-01-2020 10:40 https://www.yahoo.com OK 0.120117
The first column being date shown as 07-01-2020 in this example,
time represented by the 10:40, Link represented by https://www.google.com, Status represented by OK and latency represented by 0.080382
I currently have all the results being displayed with the following bit of code:
<?php
$file = fopen("resultsTime.csv", "r");
//Output lines until EOF is reached
while(! feof($file)) {
$line = fgets($file);
echo $line. "<br>";
}
fclose($file);
?>
This works perfectly fine as it should. However I am looking to instead enter say https://www.google.com into a text box and get the history for that site. An additional piece for that would be I only want when the status is not OK.
Hopefully that is well enough explained. I have seen some examples on here but none that offer enough detail to be able to create my own.
Thank you for your help.
Indents are a little messy here but this is the solution I came up with that works great.
Should be easily modifiable if others are looking to do the same
<center>
<form action="" method="POST">
<label>Site</label><input type="text" name="search">
<input type="submit" name="submit" value="search">
</form>
</center>
<center>
<?php
if (isset($_POST['submit'])) {
$word = $_POST['search'];
print "<tr><td><u>Date</u><td><u>Time</u></td><td><u>Site</u></td><td><u>Status</u></td><td><u>Latencey</u></td></tr>";
if (($h = fopen("resultsTime.csv", "r")) !== FALSE) {
// Convert each line into the local $data variable
while (($data = fgetcsv($h, 1000, ",")) !== FALSE) {
foreach ($data as $str) {
$site = explode(" ", $str);
if ($site[3] != "OK" && $site[2] == $word) {
print "<tr><td>" . $site[0] . "</td>";
print "<td>" . $site[1] . "</td>";
print "<td>" . $site[2] . "</td>";
print "<td>" . $site[3] . "</td>";
print "<td>" . $site[4] . "</td></tr>";
}
}
}
// Close the file
fclose($h);
}
}
?>

Table Column to hyperlink

I currently have php generating a table from csv. I use tags to identify columns, which i later use jquery and datatables to sort, filter, and highlight.
I am looking for a way to make the data from a column into links. the data is case numbers and there is a predefinited link, you would just added the case number to the end of it and that would be your link to another page.
Do anyone know how I can achieve this, I'll include a snippet below so you can get an idea of how the table is created.
<th>ASUP Created Flag</th>
</tr>
</thead>
<tbody>
END;
//here we open the csv file as read-only
$f = fopen("cases.csv", "r");
while (($line = fgetcsv($f)) !== false) {
echo "<tr>";
//this starts the alternation of tr and td for building the table
foreach ($line as $cell) {
echo "<td>" . htmlspecialchars($cell) . "</td>";
}
echo "</tr>\n";
}
fclose($f);
//after the table has been built, this is where we close it out
echo "\n</tbody></table></section></div></body></html>";
?>
Are you asking for something like:
<th>ASUP Created Flag</th>
or for the actual cell data:
foreach ($line as $cell) {
echo "<td><a href='some url'>" . htmlspecialchars($cell) . "</a></td>";
}
If you're wondering what some url should be, well that's completely up to you. If it depends on the cell data, then you would need some way to reference a URL given the cell data (either through a lookup array, database table, just some way to associate a URL with the value in $cell).
Update
If you want your case numbers to be links, and the value of the cell is the exact value you want to use in the URL, you can do something like this:
$count = 0;
foreach ($line as $cell) {
$cell = htmlspecialchars($cell);
if($count == 0) {
echo "<td><a href='/case/" . $cell . "'>" . $cell . "</a></td>";
} else {
echo "<td>" . $cell . "</td>";
}
$count++;
}

Problem with loop printing csv contents in php

This snippet just about works :|
I can spit out all of the array data, but what I want is to be able to print out the data column by column.
function processCSV()
{
global $uploadFile;
$loadLocationCsvUrl = fopen($uploadFile,"r");
if ($loadLocationCsvUrl <> false)
{
while ($locationFile = fgetcsv($loadLocationCsvUrl, ','))
{
$csvCols = array(
'country' => $locationFile[9],
'open' => $locationFile[4],
'officeid' => $locationFile[2]
);
foreach($csvCols as $locationData)
{
if ($locationData == '') {
echo "<p>" . "blank" . "</p>";
}
else
{
echo "<p>" . $locationData . "</p>";
}
}
}
}
fclose($loadLocationCsvUrl);
}
processCSV();
I thought this would work:
echo "<p>" . $locationData['country'] . "</p>";
But if I do that I see a incorrectly formatted page, like the below (uploaded screenshot).
http://www.imageupload.org/?d=9C676F041
I managed to work this out with a different implementation, I switched to a 2d array, the table rendering was never the issue it was obtaining the data.
<?php
function processCSV()
{
global $uploadFile;
$loadLocationCsvUrl = fopen($uploadFile,"r");
if ($loadLocationCsvUrl <> false)
{
while ($locationFile = fgetcsv($loadLocationCsvUrl, ','))
{
$officeId = $locationFile[2];
$country = $locationFile[9];
$open = $locationFile[4];
echo "<table>";
echo "<tr>";
echo "<td>$officeId</td>";
echo "<td>$country</td>";
echo "<td>$open</td>";
echo "</tr>";
echo "</table>";
}
}
fclose($loadLocationCsvUrl);
}
processCSV();
?>
Thank you for responding and sorry if I wasted anybodies time.
It sounds like you want to display the output colum-wise. In that case a <table> is the intended markup. But I would first simplify your code:
// read in
$csv = array_map("str_getcsv", file($uploadFile));
// output
print "<table>";
foreach ($csv as $row) {
print <<<HTML
<tr>
<td>$row[9]</td>
<td>$row[4]</td>
<td>$row[2]</td>
</tr>
HTML;
}
If you don't use the associative array keys for the columns, then there's no point in creating them.
<p> is a block element, so each successive one goes to a new line by design. You can set 'display: inline;' in your css if you want, but then why use <p>?
You could use an inline element like <span> or use 'float: left' to make a block element behave as you want.
That's assuming the data isn't appropriate for tabulation.
make a parent table then tr and td,
now, inside this td, make a table and print a column of td-trs
then close this table
print a new td in parent
repeat a table of one column trs
example....
<table><tr><td>
<table>
<tr><td>col1stuff1</td></tr>
<tr><td>col1stuff2</td><tr>
<tr><td>col1stuff3</td><tr>
</table>
</td><td>
<table>
<tr><td>col2stuff1</td></tr>
<tr><td>col2stuff2</td><tr>
<tr><td>col2stuff3</td><tr>
</table>
</td><td>
<table>
<tr><td>col3stuff1</td></tr>
<tr><td>col3stuff2</td><tr>
<tr><td>col3stuff3</td><tr>
</table>
</td></tr></table>

Library to print tabular data on a web page

Are there any libraries I can use to pretty print tabular data(from php code)?
What I mean is, if I have:
$headers = array("name", "surname", "email");
$data[0] = array("bill", "gates", "bill#microsoft.com");
$data[1] = array("steve", "jobs", "steve#apple.com");
/*...*/
pretty_print($headers, $data);
It will print my data neatly(preferably using tableless html code & css)?
Why not just write your own?
I wrote an example below. Note that I haven't tested this - it's the definition of "air code" so beware. Also, you could add checks to make sure count($rows) > 0 or to make sure count($rows) == count($headers) or whatever..
The point is just that it isn't that hard to throw something together:
function displayTable($headings, $rows) {
if !(is_array($headings) && is_array($data)) {
return false; //or throw new exception.. whatever
}
echo "<table>\n";
echo "<thead>\n";
echo "<tr>\n";
foreach($headings as $heading) {
echo "<th>" . $heading . "</th>\n";
}
echo "</tr>\n";
echo "</thead>\n";
echo "<tbody>"
foreach($data as $row) {
echo "<tr>\n";
foreach($row as $data) {
echo "<td>" . $data . "<td>";
}
echo "</tr>\n";
}
echo "</tbody>\n";
echo "</table>\n";
}
As a final note, why would you want to use HTML/CSS layouts rather than tables for this? Tables are for tabular data which this obviously is. This is their purpose!
The trend against using tables is for using them to layout pages. They're still quite valid for tabular data, and will be for the foreseeable future.

Categories