简体   繁体   中英

PHP JSON to csv with headers

I am receiving JSON from a cURL post and it looks something like the following:

{"status":"ok","sent":177,"delivered":0,"bounced":5,"hardBounced":0,"softBounced":5,"opened":[46,81],"clicked":[5,5],"notsent":[2,2],"notopened":126,"optout":0,"spam":0,"lastOpen":"1 day ago","lastClick":"13 days ago","lastOpenTS":1459808038636,"lastClickTS":1458752521593,"rebroadcast":0,"rebroadcastClick":0,"msgId":"s-04ac-1603","subject":"Blah blah Conference and Exposition","title":"Blah followup 03.22.16","sentto":["l-160f"],"suppressedon":[]}

I am editing the original post to show progress with the help of those commenting:

To view what is being converted from a json like string to an array/object:

$result = curl_exec($ch_list);
$jsonObj = print_r(json_decode($result, true));
var_dump($jsonObj);die();

Which yields the following:

Array
(
[status] => ok
[sent] => 177
[delivered] => 0
[bounced] => 5
[hardBounced] => 0
[softBounced] => 5
[opened] => Array
    (
        [0] => 46
        [1] => 81
    )

[clicked] => Array
    (
        [0] => 5
        [1] => 5
    )

[notsent] => Array
    (
        [0] => 2
        [1] => 2
    )

[notopened] => 126
[optout] => 0
[spam] => 0
[lastOpen] => 1 day ago
[lastClick] => 14 days ago
[lastOpenTS] => 1459808038636
[lastClickTS] => 1458752521593
[rebroadcast] => 0
[rebroadcastClick] => 0
[msgId] => s-04ac-1603
[subject] => AFSA Vehicle Finance Conference and Exposition
[title] => AFSA follow up 03.22.16
[sentto] => Array
    (
        [0] => l-160f
    )

[suppressedon] => Array
    (
    )

)

At this point, I am thinking alright, I have converted it into an array, which should lead to creating the csv file and I can use the code that everyone has recommended in so many posts and I did receive an error, but that was corrected by the if statement after the fopen. All together it is now creating a csv file with nothing inside of it:

$result = curl_exec($ch_list);
$jsonObj = print_r(json_decode($result));

if(!file_exists('/tmp/' . $msgId . '_' . $yearMonComb . '.csv')) {
    $f = fopen('/tmp/' . $msgId . '_' . $yearMonComb . '.csv', 'w');
    if (is_array($jsonObj) || is_object($jsonObj)) {
        $firstLineKeys = false;
        foreach ($jsonObj as $line) {
            if (empty($firstLineKeys)) {
                $firstLineKeys = array_keys($line);
                fputcsv($f, $firstLineKeys);
                $firstLineKeys = array_flip($firstLineKeys);
            }
            fputcsv($f, array_merge($firstLineKeys, $line));
        }
    }
    fclose($f);
}

What you probably want is:

$result = curl_exec($ch_list);
// Decode the JSON representation into PHP data structures
// The second argument asks to return arrays (TRUE), not objects (FALSE or missing)
$data = json_decode($result, true);

$f = fopen($filename, 'w');

// Header line: the field names (keys in $data)
fputcsv($f, array_keys($data), ',');
// Data line (can use array_values($data) or just $data as the 2nd argument)
fputcsv($f, array_values($data), ',');

fclose($f);

With the help of a co-worker and the comments that some of you made, here is what works for my situation:

$result = curl_exec($ch_list);
$jsonObj = json_decode($result, true);

$f = fopen('/tmp/' . $msgId . '_' . $yearMonComb . '.csv', 'w');
fputcsv($f, array_keys($jsonObj));
$transposed = array();

if (is_array($jsonObj)) {
    foreach($jsonObj as $key => $record){
        if(is_array($record) && count($record) > 0){
            $target = count($record) - 1;
            $transposed[$key] = $jsonObj[$key][$target];
        }else{
            $transposed[$key] = $record;
        }
    }
    fputcsv($f, array_values($transposed));
}
fclose($f);

echo $result;
curl_close($ch_list);

This is the json data after doing a print_r:

Array
(
[status] => ok
[sent] => 177
[delivered] => 0
[bounced] => 5
[hardBounced] => 0
[softBounced] => 5
[opened] => Array
    (
        [0] => 46
        [1] => 81
    )

[clicked] => Array
    (
        [0] => 5
        [1] => 5
    )

[notsent] => Array
    (
        [0] => 2
        [1] => 2
    )

[notopened] => 126
[optout] => 0
[spam] => 0
[lastOpen] => 1 day ago
[lastClick] => 14 days ago
[lastOpenTS] => 1459808038636
[lastClickTS] => 1458752521593
[rebroadcast] => 0
[rebroadcastClick] => 0
[msgId] => s-04ac-1603
[subject] => Blah blah Conference and Exposition
[title] => Blah blah follow up 03.22.16
[sentto] => Array
    (
        [0] => l-160f
    )

[suppressedon] => Array
    (
    )

)

The result was a 398 byte csv file.

To answer @axiac's question with the case where the array has an array as it's value. The conditional tests for an array:

if(is_array($record) && count($record) > 0)

If there is an array, then get the last element of the array.

I hope this helps someone, because this was driving me nuts

Another edit because I found a way to loop through an array of an array

I created a separate php file to gather the items that are arrays within the array - with the array being in the item $jsonObj['result'] of the parent array

        $jsonObj = json_decode($result, true);
        $f = fopen($value . '-sent.csv', 'w');

        $headers = array('listid', 'name', 'when', 'recid', 'email', 'ts');

        if (is_array($jsonObj)) {
            fputcsv($f, $headers);
            foreach ($jsonObj['result'] as $fields) {
                fputcsv($f, $fields);
            }
        }
        fclose($f);

        curl_close($ch_list);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM