PHP: JSON in CSV konvertieren

canju

Erfahrenes Mitglied
Hallo ihr Lieben,

ich bin hier gerade am verweifeln und hoffe ihr könnt mir (mal) wieder helfen.

Ich lade mir über einen api call via basic auth eine .json datei auf einen ftp.
Ich möchte diese .json Datei jetzt mit PHP in eine .csv Datei convertieren. Ich kriege das einfach nicht hin (ich würde am liebsten gerade in den Tisch beißen). Habe schon einige Scripte vergebens ausprobiert. meist ist der Fehler, dass nach dem json_decode kein Array vorliegt.

Der Inhalt der .json Datei sieht so aus:

JSON:
{
   "status_code":200,
   "status_message":"OK",
   "data":[
      {
         "id":1234565,
         "status":"confirmed",
         "amount_net":453,
         "created":"2019-10-15 12:00:00",
         "tracking":"rrkkdje3-343-3434",
         "product":"car",
         "gclid":null,
         "referer_url":"",
         "cancel_reason":null
      },
      {
         "id":9876363,
         "status":"verg\u00fctet",
         "amount_net":13,
         "created":"2019-10-19 12:00:00",
         "tracking":"0984dd-e9934",
         "insurance":"boat",
         "gclid":null,
         "referer_url":"",
         "cancel_reason":null
      }
   ]
}

Ich bräuchte jetzt die "Datensätze" innerhalb von "data":[...] jeweils als eigene Zeile in der .csv Datei. Inkl. Überschriften.

Könte mir evtl. einer von euch Profis mit einem kleinen PHP Snippet das die json datei in csv konvertiert aushelfen?

Grüße,
Canju
 
Lösung
Statt die Resultate einfach hinter einander zu hängen, müssen wir die Arrays zusammen führen durch die Funktion array_merge:
PHP: array_merge - Manual
(Ein Kommentar dort sagt, dass das Anhängen mit einer Schleife um Längen schneller ist aber um den Code kurz zu halten habe ich mal array_merge verwendet).
Code:
$bearer_token = 'token';
//API KEY AND PASSWORD
$headers = array("Authorization: Bearer $bearer_token", 'Content-Type: application/json');
$current_datetime = date("Y-m-d H:i:s");
$script_name = $_SERVER['SCRIPT_NAME'];
$dateObj = new DateTime();
$dateObj->modify('-12 months');
$responseArr = [];
for ($i = 0; $i < 13; $i++) {
    // prepare start and end time and URL:
    $start_date = $dateObj->format('Y-m-d')...
OK, dann passt es ja erstmal soweit.
Habe zur Sicherheit max_execution_time und max_input_time jeweils auf 600 gesetzt.
 
Habe doch noch eine Frage. Ich verwende die json Datei in einem ETL Service, der - so vermute ich - Probleme mit der ersten und /oder zweiten eckigen Klammer in der response hat.
JSON:
[
    [
        {
            "id": 6565465,
            "url": "http:\/\/www.example.me",
            "advertiserId": 644554,
            "publisherId": 8864456,
            "commissionSharingPublisherId": null,
            "commissionSharingSelectedRatePublisherId": null,
            "campaign": null,
            "siteName": "http:\/\/www.example.me",
            "commissionStatus": "declined",
            "commissionAmount": {
                "amount": 432,
                "currency": "EUR"
            },
            "saleAmount": {
                "amount": 1,
                "currency": "EUR"
            },
            "ipHash": "-34343435454453",
            "customerCountry": "DE",
            "clickRefs": {
                "clickRef": "rerere445454"
            },
            "clickDate": "2020-11-19T16:52:00",
            "transactionDate": "2020-11-19T16:52:00",
            "validationDate": "2021-04-26T17:04:00",
            "type": "Commission group transaction",
            "declineReason": "kein Vertrag zustande gekommen",
            "voucherCodeUsed": false,
            "voucherCode": null,
            "lapseTime": 33,
            "amended": false,
            "amendReason": null,
            "oldSaleAmount": null,
            "oldCommissionAmount": null,
            "clickDevice": "Apple Mac",
            "transactionDevice": "Apple Mac",
            "customerAcquisition": null,
            "publisherUrl": null,
            "advertiserCountry": "DE",
            "orderRef": null,
            "customParameters": [
                {
                    "key": "1",
                    "value": "ebfc5c38-9711-4def-932e-64fgthtger456iio7+443303"
                }
            ],
            "transactionParts": [
                {
                    "commissionGroupId": 693456,
                    "amount": 1,
                    "commissionAmount": 432,
                    "advertiserCost": null,
                    "commissionGroupCode": "commissionGroupCode",
                    "commissionGroupName": "commissionGroupName",
                    "trackedParts": [
                        {
                            "code": "code",
                            "amount": 1,
                            "currency": "EUR"
                        }
                    ]
                }
            ],
            "paidToPublisher": false,
            "paymentId": 0,
            "transactionQueryId": 0,
            "originalSaleAmount": null,
            "advertiserCost": {
                "amount": null,
                "currency": null
            },
            "basketProducts": null
        }
    ]
]

kriegen wir die noch weg, sodass das Ergebnis dann so:

JSON:
[
    {
        "id": 6565465,
        "url": "http:\/\/www.example.me",
        "advertiserId": 644554,
        "publisherId": 8864456,
        "commissionSharingPublisherId": null,
        "commissionSharingSelectedRatePublisherId": null,
        "campaign": null,
        "siteName": "http:\/\/www.example.me",
        "commissionStatus": "declined",
        "commissionAmount": {
            "amount": 432,
            "currency": "EUR"
        },
        "saleAmount": {
            "amount": 1,
            "currency": "EUR"
        },
        "ipHash": "-34343435454453",
        "customerCountry": "DE",
        "clickRefs": {
            "clickRef": "rerere445454"
        },
        "clickDate": "2020-11-19T16:52:00",
        "transactionDate": "2020-11-19T16:52:00",
        "validationDate": "2021-04-26T17:04:00",
        "type": "Commission group transaction",
        "declineReason": "kein Vertrag zustande gekommen",
        "voucherCodeUsed": false,
        "voucherCode": null,
        "lapseTime": 33,
        "amended": false,
        "amendReason": null,
        "oldSaleAmount": null,
        "oldCommissionAmount": null,
        "clickDevice": "Apple Mac",
        "transactionDevice": "Apple Mac",
        "customerAcquisition": null,
        "publisherUrl": null,
        "advertiserCountry": "DE",
        "orderRef": null,
        "customParameters": [
            {
                "key": "1",
                "value": "ebfc5c38-9711-4def-932e-64fgthtger456iio7+443303"
            }
        ],
        "transactionParts": [
            {
                "commissionGroupId": 693456,
                "amount": 1,
                "commissionAmount": 432,
                "advertiserCost": null,
                "commissionGroupCode": "commissionGroupCode",
                "commissionGroupName": "commissionGroupName",
                "trackedParts": [
                    {
                        "code": "code",
                        "amount": 1,
                        "currency": "EUR"
                    }
                ]
            }
        ],
        "paidToPublisher": false,
        "paymentId": 0,
        "transactionQueryId": 0,
        "originalSaleAmount": null,
        "advertiserCost": {
            "amount": null,
            "currency": null
        },
        "basketProducts": null
    }
]

oder so:

JSON:
{
    "id": 6565465,
    "url": "http:\/\/www.example.me",
    "advertiserId": 644554,
    "publisherId": 8864456,
    "commissionSharingPublisherId": null,
    "commissionSharingSelectedRatePublisherId": null,
    "campaign": null,
    "siteName": "http:\/\/www.example.me",
    "commissionStatus": "declined",
    "commissionAmount": {
        "amount": 432,
        "currency": "EUR"
    },
    "saleAmount": {
        "amount": 1,
        "currency": "EUR"
    },
    "ipHash": "-34343435454453",
    "customerCountry": "DE",
    "clickRefs": {
        "clickRef": "rerere445454"
    },
    "clickDate": "2020-11-19T16:52:00",
    "transactionDate": "2020-11-19T16:52:00",
    "validationDate": "2021-04-26T17:04:00",
    "type": "Commission group transaction",
    "declineReason": "kein Vertrag zustande gekommen",
    "voucherCodeUsed": false,
    "voucherCode": null,
    "lapseTime": 33,
    "amended": false,
    "amendReason": null,
    "oldSaleAmount": null,
    "oldCommissionAmount": null,
    "clickDevice": "Apple Mac",
    "transactionDevice": "Apple Mac",
    "customerAcquisition": null,
    "publisherUrl": null,
    "advertiserCountry": "DE",
    "orderRef": null,
    "customParameters": [
        {
            "key": "1",
            "value": "ebfc5c38-9711-4def-932e-64fgthtger456iio7+443303"
        }
    ],
    "transactionParts": [
        {
            "commissionGroupId": 693456,
            "amount": 1,
            "commissionAmount": 432,
            "advertiserCost": null,
            "commissionGroupCode": "commissionGroupCode",
            "commissionGroupName": "commissionGroupName",
            "trackedParts": [
                {
                    "code": "code",
                    "amount": 1,
                    "currency": "EUR"
                }
            ]
        }
    ],
    "paidToPublisher": false,
    "paymentId": 0,
    "transactionQueryId": 0,
    "originalSaleAmount": null,
    "advertiserCost": {
        "amount": null,
        "currency": null
    },
    "basketProducts": null
}

aussieht?
 
Statt die Resultate einfach hinter einander zu hängen, müssen wir die Arrays zusammen führen durch die Funktion array_merge:
PHP: array_merge - Manual
(Ein Kommentar dort sagt, dass das Anhängen mit einer Schleife um Längen schneller ist aber um den Code kurz zu halten habe ich mal array_merge verwendet).
Code:
$bearer_token = 'token';
//API KEY AND PASSWORD
$headers = array("Authorization: Bearer $bearer_token", 'Content-Type: application/json');
$current_datetime = date("Y-m-d H:i:s");
$script_name = $_SERVER['SCRIPT_NAME'];
$dateObj = new DateTime();
$dateObj->modify('-12 months');
$responseArr = [];
for ($i = 0; $i < 13; $i++) {
    // prepare start and end time and URL:
    $start_date = $dateObj->format('Y-m-d');
    $dateObj->modify('+30 days');
    $end_date = $dateObj->format('Y-m-d');
    $url = 'https://webentwicklung.ulrichbangert.de/testget-json-2.php?startDate=' . $start_date . 'T00%3A00%3A00&endDate=' . $end_date . 'T00%3A00%3A00&timezone=Europe/Berlin&dateType=transaction';
    echo 'url=' . $url . '<br>';
    // fetch from API by use of curl:
    $ch = curl_init($url) or die($current_datetime . " - " . $script_name . " - Couldnt reach endpoint \n");
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    $data = curl_exec($ch);
    echo 'response=' . $data . '<br>';
    $data = json_decode($data, true);
    $responseArr = array_merge($responseArr, $data);
}
echo ('<pre>');
var_dump($responseArr);
echo ('<pre>');
file_put_contents('test-get-json.json', json_encode($responseArr, JSON_PRETTY_PRINT));
 
Lösung
Ich muss doch nochmal nerven. Wir haben uns entschieden den ETL Service für diesen API Endpunkt nicht zu nutzen. Daher probiere ich nun selbst die json daten in eine MariaDB (10.3) zu importieren, doch ich bekomme immer die Meldung:

Code:
PHP Notice:  Undefined index: id in /path/to/file.php on line 13
PHP Notice:  Undefined index: /path/to/file.php on line 14
PHP Notice:  Trying to access array offset on value of type null in /path/to/file.php on line 14

Das ist der Code den ich bisher habe:
PHP:
<?php
// Load the database configuration file
include_once 'dbConfig.php';

$table_name = 'tabellen_name';
//read the json file contents
$jsondata = file_get_contents('path/to/file.json');

//convert json object to php associative array
$data = json_decode($jsondata, true);

//get data details
$id = $data['id'];
$commission = $data['transactionParts']['commissionAmount'];

if($id == '' OR !isset($id)){$id = null;};
if($commission == '' OR !isset($commission)){$commission = null;};

//insert into mysql table
$insert_data = <<<SQL
INSERT INTO $table_name(
              id,
              commission
            )
            VALUES(
              '$id',
              '$commission'
            )
SQL;

$db->query($insert_data);

if(!mysqli_query($db, $insert_data))
{
    die('Error : ' . mysql_error());
}
mysqli_close($db);
?>

Das json sieht so aus:

JSON:
[
    {
        "id": 6565465,
        "url": "http:\/\/www.example.me",
        "advertiserId": 644554,
        "publisherId": 8864456,
        "commissionSharingPublisherId": null,
        "commissionSharingSelectedRatePublisherId": null,
        "campaign": null,
        "siteName": "http:\/\/www.example.me",
        "commissionStatus": "declined",
        "commissionAmount": {
            "amount": 432,
            "currency": "EUR"
        },
        "saleAmount": {
            "amount": 1,
            "currency": "EUR"
        },
        "ipHash": "-34343435454453",
        "customerCountry": "DE",
        "clickRefs": {
            "clickRef": "rerere445454"
        },
        "clickDate": "2020-11-19T16:52:00",
        "transactionDate": "2020-11-19T16:52:00",
        "validationDate": "2021-04-26T17:04:00",
        "type": "Commission group transaction",
        "declineReason": "kein Vertrag zustande gekommen",
        "voucherCodeUsed": false,
        "voucherCode": null,
        "lapseTime": 33,
        "amended": false,
        "amendReason": null,
        "oldSaleAmount": null,
        "oldCommissionAmount": null,
        "clickDevice": "Apple Mac",
        "transactionDevice": "Apple Mac",
        "customerAcquisition": null,
        "publisherUrl": null,
        "advertiserCountry": "DE",
        "orderRef": null,
        "customParameters": [
            {
                "key": "1",
                "value": "ebfc5c38-9711-4def-932e-64fgthtger456iio7+443303"
            }
        ],
        "transactionParts": [
            {
                "commissionGroupId": 693456,
                "amount": 1,
                "commissionAmount": 432,
                "advertiserCost": null,
                "commissionGroupCode": "commissionGroupCode",
                "commissionGroupName": "commissionGroupName",
                "trackedParts": [
                    {
                        "code": "code",
                        "amount": 1,
                        "currency": "EUR"
                    }
                ]
            }
        ],
        "paidToPublisher": false,
        "paymentId": 0,
        "transactionQueryId": 0,
        "originalSaleAmount": null,
        "advertiserCost": {
            "amount": null,
            "currency": null
        },
        "basketProducts": null
    }
]

Kannst / könnt du / ihr mir nochmal helfen bitte?

Grüße,
canju
 
Ohne das zu testen scheint mir die Sache eindeutig zu sein: Die Daten enthalten ein Array mit nur einem Element (voraus gesetzt, dass Du es nicht gekürzt hast) und darin dann ein ass. Array mit den Elementen. D. h. Du müsstest auf die ID so zugreifen:
Code:
$id = $data[0]['id'];
 
Mein Retter! Daran lags, mit:
PHP:
$id = $data[0]['id'];
$commission = $data[0]['transactionParts'][0]['commissionAmount'];
bekomme ich jetzt die werte ausgegeben.
Danke dir vielmals (mal wieder :))
 
Mit einem simplen
PHP:
var_dump($data);
hättest du das selber herausfinden können.
 
ich bin leider absoluter newbie scatello...wirst du bestimmt schon gemerkt haben...

wenn ich das php script ausführe, dann werden nur 2 einträge in die db geschrieben, also denke ich brauche ich weider eine schleife um alle einträge in die db zu schreiben?
hab mich an einer for schleife probiert (bitte nicht lachen):
PHP:
<?php
// Load the database configuration file
include_once 'dbConfig.php';

$table_name = 'tabellen_name';
//read the json file contents
$jsondata = file_get_contents('path/to/file.json');

//convert json object to php associative array
$data = json_decode($jsondata, true);

//get data details
$id = $data['id'];
$commission = $data['transactionParts']['commissionAmount'];

if($id == '' OR !isset($id)){$id = null;};
if($commission == '' OR !isset($commission)){$commission = null;};

//insert into mysql table
for ($i = 0; $i < count($data); $i++) {
$insert_data = <<<SQL
INSERT INTO $table_name(
              id,
              commission
            )
            VALUES(
              '$id',
              '$commission'
            )
SQL;
}


$db->query($insert_data);

if(!mysqli_query($db, $insert_data))
{
    die('Error : ' . mysql_error());
}
mysqli_close($db);
?>

aber es bleibt bei 2 Einträgen, die in die DB geschrieben werden. Es sind aber insgeamt 3427 Einträge in der json datei vorhanden (gibt mir echo count($data); aus). Was mache ich falsch?
 
Zurück