juppix: JSON - falsches Format

Moin zusammen,

ich habe ein Problem. Ich benötige eine JSON-Ausgabe für eine AJAX-Tabellen-Komponente in folgendem Format (Beispiel der Komponente):

{
data: [
[
"Tiger Nixon",
"System Architect",
"Edinburgh",
"5421",
"2011/04/25",
"$320,800"
],
[
"Garrett Winters",
"Accountant",
"Tokyo",
"8422",
"2011/07/25",
"$170,750"
],
[
"Ashton Cox",
"Junior Technical Author",
"San Francisco",
"1562",
"2009/01/12",
"$86,000"
],

Nun habe ich folgenden Snippet gefunden, der meine mysql-Abfrage in JSON umwandelt via PHP:

	 $sql = "SELECT * FROM ...");
		
   $result = mysql_query($sql);	
	
	/* pealing the array data from db object */        
    while ($row = mysql_fetch_assoc($result)) { 
        $data[] = $row;		
    }
  
    /* checking if data has no rows */
    if(isset($data)){
        /* convert data to json */		
        $json = json_encode($data);
    }else{
        /* set nothing to return */
        $json = null;
    }
 
    /* return the json result */	
    echo $json;
?>

Das funktioniert soweit ganz gut - sogar der Browser erkennt das korrekte JSON und formatiert es korrekt. LEIDER wird nicht exakt das Format ausgegeben, wie es erwartet wird und ich es benötige. Es erscheint nämlich:

[
{
id: "1",
typ_id: "1",
day: "2018-02-21 00:00:00",
users_id: "1",
text_short: "k",
text_long: "Krank"
},
{
id: "1",
typ_id: "1",
day: "2018-02-22 00:00:00",
users_id: "1",
text_short: "k",
text_long: "Krank"
},

Wie man sieht beginnt es nicht mit "{", sondern "[". ... und das "data:" usw. fehlt auch.

Wie kriege ich es denn EXAKT so formatiert wie die Ausgabe ganz oben?

1000 dank u. grüße jup

akzeptierte Antworten

  1. @@juppix

    {
    data: [
    [
    "Tiger Nixon",
    

    Das ist kein JSON. Du willst "data"?

    Wie man sieht beginnt es nicht mit "{", sondern "[". ... und das "data:" usw. fehlt auch.

    Vielleicht deshalb?

    LLAP 🖖

    --
    „Wer durch Wissen und Erfahrung der Klügere ist, der sollte nicht nachgeben. Und nicht aufgeben.“ —Kurt Weidemann
  2. Tach!

    Wie kriege ich es denn EXAKT so formatiert wie die Ausgabe ganz oben?

    Indem du eine Datenstruktur erstellst, die dem gewünschten Ergebnis entspricht, also kein Array of Objects sondern ein Array of Arrays. Für die Datensätze muss dabei jeweils ein Array angelegt werden, in das in der gewünschten Reihenfolge die Werte aus den Eigenschaften des Objekts geschrieben werden.

    dedlfix.

    1. Oh Mann... das kann doch nicht so schwer sein:

      hier ist das alles beschrieben:

      https://www.datatables.net/examples/data_sources/ajax.html

      Und da steht sogar:

      The ajax option also allows for more advanced configuration such as altering how the Ajax request is made.

      Aber ich raffe es einfach nicht.

      Man sollte doch per PHP-Funktion irgendwie recht simple ein valides JSON erzeugen können ohne sich selbst einen "generator" bauen zu müssen?!

      1. Tach!

        Man sollte doch per PHP-Funktion irgendwie recht simple ein valides JSON erzeugen können ohne sich selbst einen "generator" bauen zu müssen?!

        JSON ist ein sehr flexibles Format. Wenn Anwendung X eine bestimmte Struktur haben möchte, muss man diese Struktur erzeugen. Und das geht nicht von selbst.

        Ganz simpel geht nur, eine vorhandene Datenstruktur mit json_encode() ins JSON-Format bringen. Dann sieht das Ergebnis aber entsprechend dem Original aus. Wenn du ein bestimmtes Format haben möchtest, das nicht dem Original entspricht, musst du es entsprechend umformatieren.

        dedlfix.

      2. Tach!

        hier ist das alles beschrieben:

        https://www.datatables.net/examples/data_sources/ajax.html

        Unter anderem ist da auch beschrieben, dass man auch Objekte übergeben kann.

        dedlfix.

        1. Okay... aber ich habe dieses "Data" Objekt ja gar nicht…

          und folgender Code wirft einen Fehler (ohne "Data"):

          <script>
          $(document).ready(function() {
              $('#example').DataTable( {
                  "ajax": './getCalendarData.php',
                  "columns": [
                      { "name" },
                      { "position" },
                      { "office" },
                      { "extn" },
                      { "start_date" },
                      { "salary" }
                  ]
              } );
          } );
          </script>
          
          
          1. Das sollte es nun sein:

            <script>
            $(document).ready(function() {
                $('#example').DataTable( {
                    "ajax": './getCalendarData.php',
            		"dataSrc":'',
            		"columns": [
            			{ "data": "id" },
            			{ "data": "typ_id" },
            			{ "data": "day" },
            			{ "data": "users_id" },
            			{ "data": "text_short" },
            			{ "data": "text_long" }
            	]
            	} );
            } );
            </script>
            

            Aber ich erhalte in der Konsole den Fehler:

            Uncaught TypeError: Cannot read property 'length' of undefined

            at datatables.min.js:89
            at i (datatables.min.js:76)
            at Object.success (datatables.min.js:76)
            at i (datatables.min.js:14)
            at Object.fireWith [as resolveWith] (datatables.min.js:14)
            at A (datatables.min.js:16)
            at XMLHttpRequest.<anonymous> (datatables.min.js:16)
            

            (anonymous) @ datatables.min.js:89 i @ datatables.min.js:76 success @ datatables.min.js:76 i @ datatables.min.js:14 fireWith @ datatables.min.js:14 A @ datatables.min.js:16 (anonymous) @ datatables.min.js:16 load (async) send @ datatables.min.js:16 ajax @ datatables.min.js:16 sa @ datatables.min.js:77 ga @ datatables.min.js:89 e @ datatables.min.js:133 (anonymous) @ datatables.min.js:133 each @ datatables.min.js:14 each @ datatables.min.js:14 m @ datatables.min.js:123 h.fn.DataTable @ datatables.min.js:205 (anonymous) @ ?p=calendar:51 j @ datatables.min.js:14 k @ datatables.min.js:14 setTimeout (async) (anonymous) @ datatables.min.js:14 i @ datatables.min.js:14 fireWith @ datatables.min.js:14 fire @ datatables.min.js:14 i @ datatables.min.js:14 fireWith @ datatables.min.js:14 ready @ datatables.min.js:14 S @ datatables.min.js:15

            1. Hallo juppix,

              siehste, da hast Du schon mehr herausgefunden als ich. Herzlichen Glückwunsch, die Energie des Verstehens springt über 😉

              Die dataSrc-Eigenschaft ist eine Unter-Eigenschaft der ajax-Eigenschaft, und nicht eigenständig. Also so:

               $('#example').DataTable( {
                  "ajax": {
                      "url": './getCalendarData.php',
                      "dataSrc": ''
                  }
              		"columns": [ ... ]
              	} );
              

              und ja, dann sollte dieses Kapsel-Objekt mit der data-Eigenschaft unnötig sein.

              Rolf

              --
              sumpsi - posui - clusi
              1. 1000 Dank für Deine Hilfe und den 1 A support hier 😉

                Hier der Code, der nun klappt :

                
                <script>
                $(document).ready(function() {
                    $('#example').DataTable( {
                        "ajax": { 
                			"url": "./getCalendarData.php",
                			"dataSrc": ""
                		},		
                		"columns": [
                			{ "data": "id" },
                			{ "data": "typ_id" },
                			{ "data": "day" },
                			{ "data": "users_id" },
                			{ "data": "text_short" },
                			{ "data": "text_long" }
                		]
                	} );
                } );
                </script>
                
                

                Einfach großartig!

          2. Hallo juppix,

            (Edit: Habe das hier geschrieben während Du selbst auf das meiste davon gekommen bist)

            wenn ich das richtig lese, dann will diese DataTables Komponente - sofern man nichts anderes festlegt - ein Objekt mit einer einzigen Eigenschaft. Diese Eigenschaft heißt "data", und der Wert muss ein Array sein.

            Die Zeilen dieses Arrays können unterschiedlich strukturiert sein. Im einfachsten Fall ist eine Zeile des data-Array wiederum ein Array mit den Werten für die Spalten. Dann brauchst Du keine columns-Definition zu machen. Aber Du musst im PHP dafür sorgen, dass dein json genau diese Struktur liefert.

            Wenn Du was anderes liefern willst, musst Du die Spalten mappen - aber an einem kommst Du nicht vorbei, denke ich: an dem Objekt mit der data-Eigenschaft, dessen Inhalt ein Array ist. Das kannst Du in PHP ganz leicht herstellen, indem Du assoziative Arrays nutzt:

            $ergebnis = array("data" => $zeilen);
            echo json_encode($ergebnis);
            

            $zeilen muss wiederum ein Array sein, mit numerischen Indexen fortlaufend nummeriert - also das, was du mit $zeilen[] = $zeile automatisch bekommst.

            Den Inhalt von $zeile musst Du selbst erzeugen. Am einfachsten ist es wohl, wenn Du nicht fetch_assoc machst, sondern fetch_row. Und zwar NICHT mysql_fetch_row, sondern mysqli_fetch_row oder ein Zugriff über PDO. Die mysql-Erweiterung ist schon seit langem wegen schwerer Sicherheitsprobleme durch mysqli ersetzt worden.

            Du musst dafür auch noch deinen SELECT * ändern. Sowas macht man in Programmen nicht, man schreibt jede Spalte explizit hin, die man will, so dass die Reihenfolge und die Anzahl der gelieferten Spalten klar definiert ist. SELECT * ist für interaktive Tools ok, bei denen das Ergebnis nur angezeigt und nicht automatisch weiterverarbeitet wird. In einem Programm ist es eine scharfe Tretmine.

            An Stelle von fetch_row kannst Du natürlich auch fetch_assoc verwenden. Aber dann musst Du der DataTable definieren, unter welchem Key es welchen Spalteninhalt findet. Das machst Du mit der columns-Eigenschaft - aber da trägst Du nicht nur die Spaltennamen ein. Über columns kann man noch mehr festlegen als nur den Spaltennamen in der Datenquelle, darum sind die Einträge im columns-Array Objekte. Das Spalten-Mapping machst Du mit der data-Eigenschaft eines solchen Objekts.

            Jedenfalls wird DataTables nur dann funktionieren, wenn Du Dich exakt an die Anleitung hältst. Freistil-Syntax verstehen nur Menschen, nicht die heutigen Computer.

            Rolf

            --
            sumpsi - posui - clusi