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')...
Ach entschuldige das war nicht der inhalt der test-get-json.json sondern habe mir via
php /pfad/zur/datei.php >> test_file.txt das ergebnis ausgeben lassen.
War nur gut zu sehen, dass das api limit überschritten wurde.

Inhalt der test-get-json.json sieht so aus:

JSON:
[
    [],
    [],
    [],
    [],
    [
        {
            "id": 259630312,
            "url": "http://www.publisher.com",
            "advertiserId": 7052,
            "publisherId": 189069,
            "commissionSharingPublisherId": 55555,
            "commissionSharingSelectedRatePublisherId": 189069,
            "campaign": "campaign name"
            "siteName": "Publisher",
            "commissionStatus": "pending",
            "commissionAmount": {
              "amount": 5.59,
              "currency": "GBP"
            },
            "saleAmount": {
              "amount": 55.96,
              "currency": "GBP"
            },
            "ipHash": "-66667778889991112223",
            "customerCountry": "GB",
            "clickRefs": {
              "clickRef": "12345",
              "clickRef2": "22222",
              "clickRef3": "33333",
              "clickRef4": "44444",
              "clickRef5": "55555",
              "clickRef6": "66666"
            },
            "clickDate": "2017-01-23T12:18:00",
            "transactionDate": "2017-02-20T22:04:00",
            "validationDate": null,
            "type": "Commission group transaction",
            "declineReason": null,
            "voucherCodeUsed": true,
            "voucherCode": "example123",
            "lapseTime": 2454307,
            "amended": false,
            "amendReason": null,
            "oldSaleAmount": null,
            "oldCommissionAmount": null,
            "clickDevice": "Windows",
            "transactionDevice": "Windows",
            "publisherUrl": "http://www.publisher.com/search?query=dvds",
            "advertiserCountry": "GB",
            "orderRef": "111222333444",
            "customParameters": [
              {
                "key": "1",
                "value": "555666"
              },
              {
                "key": "2",
                "value": "example entry"
              },
              {
                "key": "3",
                "value": "LLLMMMNNN"
              }
            ],
            "transactionParts": [
              {
                "commissionGroupId": 12345,
                "amount": 44.76,
                "commissionAmount": 4.50,
                "commissionGroupCode": "DEFAULT",
                "commissionGroupName": "Default Commission"
              }
        
              {
        
                "commissionGroupId": 654321,
                "amount": 11.20,
                "commissionAmount": 1.50,
                "commissionGroupCode": "EXISTING",
                "commissionGroupName": "EXISTING"
              }
        
        
            ],
            "paidToPublisher": false,
            "paymentId": 0,
            "transactionQueryId": 0,
            "originalSaleAmount": null
          }
    ]
    ],
    [],
    [],
    [],
    [],
    [],
    [],
    [],
    []
]
 
Hm, wir schicken ja nur 13 Requests raus. Kann es vielleicht sein, dass Du beim Testen das Skript häufiger aufgerufen hast und dass es dadurch zu der Überschreitung gekommen ist? Ist ja häufig so beim Testen.
 
Oder ist vielleicht der Text der Fehlermeldung irreführend: 60 sec / 20 = 3 sec, so dass man nur alle 3 sec einen Request schicken darf?
 
Ja, gut möglich , dass ich zwei mal zu schnell hintereinander ausgeführt habe. Habe es gerade nochmal ausgeführt, kam keine Fehlermeldung mehr.

Könntest du mir evtl. noch eine Zeitverzögerung zwischen den einzelnen requests einbauen, die ich per variable ändern kann? *liebguck. Sodass quasi sagen wir 30 sekunden zwischen jedem request gewartet wird bevor der nächste gesendet wird

Ich vermute ich muss doch weiter in die Vergangenheit gehen als 12 Monate und wir haben noch einige andere services, die diesen Endpunkt ansprechen.
 
Dafür gibt es die Funktion sleep mit der Anzahl von Sekunden als Parameter. Rufe sie am Ende der Schleife auf:
Code:
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.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[] = $data;
    sleep(30);
}
Du musst nur aufpassen, weil dann das Skript relativ lange läuft: 30 * 13 sec plus die Antwortzeiten auf die API.
 
Man könnte auch das Skript zyklisch aufrufen durch einen Cronjob mit 30 sec. Dann hättest Du das Problem mit der langen Laufzeit nicht.
 
Man könnte auch das Skript zyklisch aufrufen durch einen Cronjob mit 30 sec. Dann hättest Du das Problem mit der langen Laufzeit nicht.
ja ist vielleicht die sicherere variante. ich habs jetzt auf jeden fall schonmal mit sleep(4) und 24 monaten laufen lassen. ist nicht in den timeout gegangen.

weiß gar nicht wie ich das wieder gut machen kann, hast mir sehr geholfen @Sempervivum, vielen lieben dank nochmal.

ich mach jetzt erstmal feierabend und bastel morgen weiter.
 
Zurück