How to modify json to validate it? - php

I am downloading some json and merging them, but while doing that it creates a string like below,
}
][
{
I'd like to replace that with a comma in order to have a valid json
I tried something like this but it's not working:
$datas = array();
$json = str_replace("][",",", $datas);
$json = json_encode($json, JSON_PRETTY_PRINT);
print_r($json);
If I can manage to do that I'd use the same to replace columns name (I'm actually building this json from a csv) if possible.
UPDATE
To clarify I have multiple csv(s) from which I am then building a single json
FULL CODE
header('Content-Type: application/json');
$arr = array("04-12-2020",
"04-13-2020",
"04-14-2020",
"04-15-2020",
"04-16-2020",
"04-17-2020",
"04-18-2020",
"04-19-2020",
"04-20-2020",
"04-21-2020",
"04-22-2020",
"04-23-2020",
"04-24-2020",
"04-25-2020",
"04-26-2020",
"04-27-2020",
"04-28-2020",
"04-29-2020",
"04-30-2020",
"05-01-2020",
"05-02-2020",
"05-03-2020",
"05-04-2020",
"05-05-2020",
"05-06-2020",
"05-07-2020",
"05-08-2020",
"05-09-2020",
);
foreach($arr as $date) {
$url = "https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_daily_reports_us/".$date.".csv";
if (($handle = fopen($url, "r")) !== FALSE) {
$csvs = [];
while(! feof($handle)) {
$csvs[] = fgetcsv($handle);
}
$datas = [];
$column_names = [];
foreach ($csvs[0] as $single_csv) {
$column_names[] = $single_csv;
}
foreach ($csvs as $key => $csv) {
if ($key === 0) {
continue;
}
foreach ($column_names as $column_key => $column_name) {
$datas[$key-1][$column_name] = $csv[$column_key];
}
}
$json = json_encode($datas, JSON_PRETTY_PRINT);
fclose($handle);
print_r($json);
}
}

Don't call json_encode() inside the loop. Initialize $datas outside the loop, and encode it after the loop.
$datas = [];
foreach($arr as $date) {
$url = "https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_daily_reports_us/".$date.".csv";
if (($handle = fopen($url, "r")) !== FALSE) {
$csvs = [];
while($row = fgetcsv($handle)) {
$csvs[] = $row;
}
$column_names = [];
// Use header line to get array keys
foreach ($csvs[0] as $single_csv) {
$column_names[] = $single_csv;
}
array_shift($csvs); // remove header line
foreach ($csvs as $key => $csv) {
$new_data = [];
foreach ($column_names as $column_key => $column_name) {
$new_data[$column_name] = $csv[$column_key];
}
$datas[] = $new_data;
}
fclose($handle);
}
}
$json = json_encode($datas, JSON_PRETTY_PRINT);
print_r($json);

Related

PHP script to create new csv from another csv after rearranging the data

I have a csv with following structure:
And I need the output csv as follows:
That means taking the faetures from each column and put it in the single row.
I am using php office to fetch and write the csv. I have written the following:
if ( false === $handle = fopen('../../../3b.csv', 'r') )
throw new Exception('File open failed.');
$headers = fgetcsv($handle);
$row = '';
$row = array();
$data = '';
$data = array();
while ( false !== $fields = fgetcsv($handle) ) {
$fields = array_combine($headers, $fields);
foreach($fields as $key=>$value){
if($key!='sku'){
if($value==''){
continue;
}
}
$row[$key] = $value;
}
if(sizeof($row)==1){
unset($row['sku']);
}
$row = array_filter( $row );
$data[] = $row;
}
$data = array_filter($data);
$use_keys = ['sku','AC Rating','color','Feature','Finish','Grade','Installation Location','Installation Method','Plank Style','Size','Specie','Tile Format','Warranty','Wear Layer','Width','LifeStyle',
'Material','Style','Thickness','Appearance','PEIRating','ProtectionRating'];
foreach($data as $key=>$value){
$new_arr = [];
foreach($use_keys as $apk_item) {
$new_value = '';
if (isset($data[$key][$apk_item])) {
$new_value = str_replace(",","|",$data[$key][$apk_item]);
}
$new_arr[$apk_item] = $new_value;
}
$data[$key] = $new_arr;
}
$data = array_filter($data, 'array_filter');
$final_array = array();
foreach ($data as $features) {
$product = array('feature' => '');
foreach ($features as $key => $feature) {
if ($key == 'sku') {
$product['sku'] = $feature;
}
else {
if($feature!=''){
$product['feature'] .= $key;
$product['value'] .= $feature;
}
}
}
$final_array[] = $product;
}
$final_array = array_filter($final_array);
$table = '<table border="1" id="csvtable">
<thead><tr><th>sku</th><th>feature</th><th>value</th></tr></thead>
<tbody>';
foreach($final_array as $value){
$sku = $value["sku"];
$combinedfeature = explode(",", $value['feature']);
foreach($combinedfeature as $single){
$table .= '<tr><td width="20%">'.$sku.'</td><td width="40%">'.$single['feature'].'</td><td width="40%">'.$single['value'].'</td></tr>';
}
}
$table .= '</tbody></table>';
print_r($table);
It's giving wrong output. How can I do this? Anyone can help, please?
A much more compact method would be to read the input and write out the target file in one loop.
This code reads in each line, combines it with the header and then extracts the sku (and removes it from the details). Then loops over the remaining details, and if there is a value to output it writes the output to the result file.
As each value may also be a comma separated list, this uses explode() to split them into individual items and writes them out as separate parts...
$inputFile = "a.csv";
$outputFile = "a1.csv";
$inputHandle = fopen($inputFile, 'r');
$outputHandle = fopen($outputFile, 'w');
$headers = fgetcsv($inputHandle);
fputcsv($outputHandle, ["sku", "feature", "value" ]);
while ( false !== $fields = fgetcsv($inputHandle) ) {
$fields = array_combine($headers, $fields);
$sku = $fields['sku'];
unset($fields['sku']);
foreach ( $fields as $name => $field ) {
if (!empty(trim($field))) {
$subFields = explode(",", $field );
foreach ( $subFields as $value ) {
fputcsv($outputHandle, [$sku, $name, $value]);
}
}
}
}
fclose($inputHandle);
fclose($outputHandle);

fputcsv() putting all data in one row

I'm working on reading some json, flattening it in to a single array, and then writing it to a csv. I've gotten pretty far but I am currently stuck on the last component. I'm able to pull the data, flatten it, and write it to the csv, but it for some reason it writes all of it in one row, while it should be creating a new line with each new object. I think it's happening because my flattened array is taking multiple objects and combining them in to one, but I cant figure out how to fix it. Any help would be greatly appreciated.
Here's what I have:
<?php
$csvArray = array();
function array_flatten($array, $prefix = 'new')
{
if (!is_array($array)) {
return false;
}
$result = array();
foreach ($array as $key => $value) {
if (is_array($value)) {
$result = array_merge($result, array_flatten($value, $prefix . '_' . $key));
} else {
$result[$prefix . '_' . $key] = $value;
}
}
return $result;
}
for ($x = 1; $x <= 1; $x++) {
$response = file_get_contents('https://seeclickfix.com/api/v2/issues?page=' . $x . '&per_page=2');
//Decode the JSON and convert it into an associative array.
$jsonDecoded = json_decode($response, true);
$flat = array_flatten($jsonDecoded['issues']);
//Give our CSV file a name.
$csvFileName = '/Applications/MAMP/htdocs/SeeClickFix/all_exports_3/export' . $x . '.csv';
//Open file pointer.
$fp = fopen($csvFileName, 'w');
foreach ($flat as $item) {
// fputcsv($fp, $item);
if (is_null($item) || !isset($item) || $item == "Point") {
} else {
array_push($csvArray, $item);
}
fputcsv($fp, $csvArray);
}
fclose($fp);
}
?>

Add new columns for CSV file

I have tree arrays with different lengths, and I want to display each array in a column of my csv file. That's the php script file I am using but no success; I got the data duplicated.
The attempt I tried was to feed empty cells with an empty string so that I can have 3 columns with the same lengths.
$categories = get_categories( $args );
$categories_level_1 = array();
$categories_level_2 = array();
$categories_level_3 = array();
foreach ($categories as $cat ) {
$cat_level =count( get_ancestors($cat->term_id, 'category') );
if($cat_level == 0){
$categories_level_1[] = $cat;
}else{
if($cat_level == 1){
$categories_level_2[] = $cat;
}elseif($cat_level == 2){
$categories_level_3[] = $cat;
}
}
}
fputcsv($file, array(utf8_decode('Catégories level 1')));
$i=0;
foreach ($categories_level_1 as $category) {
$i++;
$categorie_name = array(rw_mb_convert_encoding($category->name));
fputcsv($file, $categorie_name );
print_flush("\n liine created");
}
while( $i < count($categories_level_2)){
$i++;
fputcsv($file, array(" "));
print_flush("\n liine vide created");
}
fclose($file);
$newCsvData = array();
foreach ($categories_level_2 as $cat) {
if (($handle = fopen($csv_file_path, "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$data[] = rw_mb_convert_encoding($cat->name);
$newCsvData[] = $data;
}
fclose($handle);
}
}
$handle = fopen($csv_file_path, 'w');
foreach ($newCsvData as $line) {
fputcsv($handle, $line);
}
fclose($handle);
I should get my columns with the folowwing structure :
But in reality that's the result I got :

Convert json to csv using php

Hello i have small problem with converting json to csv.
Here is my code:
$jsonString = '{"cod":"200","calctime":0.3107,"cnt":15,"list":[{"id":2208791,"name":"Yafran","coord":{"lon":12.52859,"lat":32.06329},"main":{"temp":9.68,"temp_min":9.681,"temp_max":9.681,"pressure":961.02,"sea_level":1036.82,"grnd_level":961.02,"humidity":85},"dt":1485784982,"wind":{"speed":3.96,"deg":356.5},"rain":{"3h":0.255},"clouds":{"all":88},"weather":[{"id":500,"main":"Rain","description":"light rain","icon":"10d"}]}]}';
//Decode the JSON and convert it into an associative array.
$jsonDecoded = json_decode($jsonString, true);
//Give our CSV file a name.
$csvFileName = 'file.csv';
//Open file pointer.
$fp = fopen($csvFileName, 'w');
//Loop through the associative array.
foreach($jsonDecoded as $row){
//Write the row to the CSV file.
fputcsv($fp, $row);
}
//Finally, close the file pointer.
fclose($fp);
?>
I have tried with another json format like this [{"name":"Wayne","age":28},{"name":"John","age":21},{"name":"Sara","age":24}] and its working perfect.
How to modify my code to save it correctly in csv format.
Pictures:
Now it save it like this:
I need to save it like this:
Can someone help me ?
Hope this will work..
<?php
$jsonString = '{"cod":"200","calctime":0.3107,"cnt":15,"list":[{"id":2208791,"name":"Yafran","coord":{"lon":12.52859,"lat":32.06329},"main":{"temp":9.68,"temp_min":9.681,"temp_max":9.681,"pressure":961.02,"sea_level":1036.82,"grnd_level":961.02,"humidity":85},"dt":1485784982,"wind":{"speed":3.96,"deg":356.5},"rain":{"3h":0.255},"clouds":{"all":88},"weather":[{"id":500,"main":"Rain","description":"light rain","icon":"10d"}]}]}';
$jsonDecoded = json_decode($jsonString, true);
$csvHeader=array();
$csvData=array();
jsontocsv($jsonDecoded);
print_r($csvHeader);
print_r($csvData);
$csvFileName = 'file.csv';
$fp = fopen($csvFileName, 'w');
fputcsv($fp, $csvHeader);
fputcsv($fp, $csvData);
fclose($fp);
function jsontocsv($data)
{
global $csvData,$csvHeader;
foreach($data as $key => $value)
{
if(!is_array($value))
{
$csvData[]=$value;
$csvHeader[]=$key;
}
else
{
jsontocsv($value);
}
}
}
Json 2
<?php
$jsonString =file_get_contents("http://samples.openweathermap.org/data/2.5/box/city?bbox=12,32,15,37,10&appid=b1b15e88fa797225412429c1c50c122a1");;
$jsonDecoded = json_decode($jsonString, true);
$csvHeader=array();
$csvData=array();
$csvFileName = 'file.csv';
$fp = fopen($csvFileName, 'w');
$counter=0;
foreach($jsonDecoded["list"] as $key => $value)
{
jsontocsv($value);
if($counter==0)
{
fputcsv($fp, $csvHeader);
$counter++;
}
fputcsv($fp, $csvData);
$csvData=array();
}
fclose($fp);
function jsontocsv($data)
{
global $csvData,$csvHeader;
foreach($data as $key => $value)
{
if(!is_array($value))
{
$csvData[]=$value;
$csvHeader[]=$key;
}
else
{
jsontocsv($value);
}
}
}
try this:
$rowNr = 0;
$prevKey = "";
$target = [];
$iterator = new RecursiveArrayIterator($jsonDecoded['list'][$rowNr]);
iterator_apply($iterator, 'traverseStructure', array($iterator,$prevKey,&$target));
function traverseStructure($iterator, $prevKey, &$target) {
while ( $iterator -> valid() ) {
if ( $iterator -> hasChildren() ) {
$prevKey = $iterator->key();
traverseStructure($iterator -> getChildren(), $prevKey, $target);
}
else {
if(isset($prevKey) && !is_int($prevKey)){
$row1 = $prevKey."/".$iterator->key();
}else{
$row1 = $iterator->key();
}
$row2 = $iterator->current();
$target[$row1] = $row2;
}
$iterator -> next();
}
}
fputcsv($fp, array_keys($target));
fputcsv($fp, array_values($target));

Convert csv in php and get unique value

I would like to convert a csv file that has duplicate contents and i would like to sum the quantity and extract the price without sum it.
file.csv :
code,qty,price
001,2,199
001,1,199
002,2,159
002,2,159
Actual php that sum the quantiy and get a result with unique value and total qty.
<?php
$tsvFile = new SplFileObject('file.csv');
$tsvFile->setFlags(SplFileObject::READ_CSV);
$tsvFile->setCsvControl("\t");
$file = fopen('file.csv', 'w');
$header = array('sku', 'qty');
fputcsv($file, $header, ',', '"');
foreach ($tsvFile as $line => $row) {
if ($line > 0) {
if (isset($newData[$row[0]])) {
$newData[$row[0]]+= $row[1];
} else {
$newData[$row[0]] = $row[1];
}
}
}
foreach ($newData as $key => $value) {
fputcsv($file, array($key, $value), ',', '"');
}
fclose($file);
?>
the result for this is:
code,qty
001,3
002,4
and i would like to add price, but without sum it.
The result i need is:
code,qty,price
001,3,199
002,4,159
I haven't tested this yet, but I think this is what you are looking for:
<?php
$tsvFile = new SplFileObject('file.csv');
$tsvFile->setFlags(SplFileObject::READ_CSV);
$tsvFile->setCsvControl("\t");
$file = fopen('file.csv', 'w');
$header = array('sku', 'qty');
fputcsv($file, $header, ',', '"');
foreach ($tsvFile as $line => $row) {
if ($line > 0) {
if(!isset($newData[$row[0]])) {
$newData[$row[0]] = array('qty'=>0, 'price'=>$row[2]);
}
$newData[$row[0]]['qty'] += $row[1];
}
}
foreach ($newData as $key => $arr) {
fputcsv($file, array($key, $arr['qty'], $arr['price']), ',', '"');
}
fclose($file);
?>
To start with, there's a nice function on the PHP page str_getcsv which will help you end up with a more legible array to work with:
function csv_to_array($filename='', $delimiter=',') {
if(!file_exists($filename) || !is_readable($filename))
return FALSE;
$header = NULL;
$data = array();
if (($handle = fopen($filename, 'r')) !== FALSE) {
while (($row = fgetcsv($handle, 1000, $delimiter)) !== FALSE) {
if(!$header)
$header = $row;
else
$data[] = array_combine($header, $row);
}
fclose($handle);
}
return $data;
}
This is purely for legibility sake but now comes the code which would allow you to work over the array.
$aryInput = csv_to_array('file.csv', ',');
$aryTemp = array();
foreach($aryInput as $aryRow) {
if(isset($aryTemp[$aryRow['code'])) {
$aryTemp[$aryRow['code']['qty'] += $aryRow['qty'];
} else {
$aryTemp[$aryRow['code']] = $aryRow;
}
}
In the above code, it simply:
Loops through the input
Checks whether the key exists in a temporary array
If it does, it just adds the new quantity
If it doesn't, it adds the entire row
Now you can write out your expectant csv file :)

Categories