Nico R.: Fehler "unexpected token: numeric literal" beim Versuch PHP-Array zu übernehmen

Hallo zusammen,

ich versuche, ein PHP-Array in ein JS-Objekt zu überführen. Es handelt sich um ein numerisches Array, das in PHP fehlerfrei funktioniert. Aber wenn ich es versuche per

let toreArrayDB = "<?=json_encode($toreArray)?>";

als JS-Objekt zu speichern, bekomme ich in in der Konsole diese Fehlermeldung: Uncaught SyntaxError: unexpected token: numeric literal

So sieht der Variablen-Inhalt im Debugger aus:

let toreArrayDB = "{"0":["347",{"1":["10",null]}],"1":["344",{"1":["20","1"],"2":["30",null]}],"3":["338",{"1":["30",null]}]}";

Das sieht doch eigentlich nach korrektem JSON-Format aus. Oder nicht? Übersehe ich etwas? Warum lässt mich JS das nicht zumindest als String speichern?

Der Vollständigkeit halber hier noch das PHP-Array:

array(3) {
  [0]=>
  array(2) {
    [0]=>
    string(3) "347"
    [1]=>
    array(1) {
      [1]=>
      array(2) {
        [0]=>
        string(2) "10"
        [1]=>
        NULL
      }
    }
  }
  [1]=>
  array(2) {
    [0]=>
    string(3) "344"
    [1]=>
    array(2) {
      [1]=>
      array(2) {
        [0]=>
        string(2) "20"
        [1]=>
        string(1) "1"
      }
      [2]=>
      array(2) {
        [0]=>
        string(2) "30"
        [1]=>
        NULL
      }
    }
  }
  [3]=>
  array(2) {
    [0]=>
    string(3) "338"
    [1]=>
    array(1) {
      [1]=>
      array(2) {
        [0]=>
        string(2) "30"
        [1]=>
        NULL
      }
    }
  }
}

Schöne Grüße

Nico

  1. Jetzt, wo ich nochmal draufgestarrt habe, ist mir doch noch ein Licht aufgegangen. Die Kombination aus ="{" ging natürlich nicht. Mit

    let toreArrayDB = '<?=json_encode($toreArray)?>';
    

    hats funktioniert.

    Gute Nacht ;-)

    1. Hi,

      Jetzt, wo ich nochmal draufgestarrt habe, ist mir doch noch ein Licht aufgegangen. Die Kombination aus ="{" ging natürlich nicht. Mit

      let toreArrayDB = '<?=json_encode($toreArray)?>';
      

      hats funktioniert.

      aber eher zufällig, weil kein ' in den Werten vorkommt.

      Escaping ist das Stichwort. Bzw. in deutscher Sprache: Kontextwechsel.

      cu,
      Andreas a/k/a MudGuard

    2. @@Nico R.

      Jetzt, wo ich nochmal draufgestarrt habe, ist mir doch noch ein Licht aufgegangen. Die Kombination aus ="{" ging natürlich nicht. Mit

      let toreArrayDB = '<?=json_encode($toreArray)?>';
      

      hats funktioniert.

      Ja, wenn du " außen als Stringbegrenzer verwendest, darf im String natürlich kein nicht-escapetes " sein. Da ist ' als Stringbegrenzer zu verwenden richtig. Und, wie @MudGuard schon anmerkte, darf dann natürlich kein nicht-escapetes ' im String sein.

      (Sollten welche vorkommen, müssten sie entweder als \' escapet werden oder – wenn es sich um Text handelt – durch richtige Apostrophe ersetzt werden.)

      Andersrum außen " und innen ' würde nicht funktionieren, da das JSON-Format nur ", aber nicht ' als Stringbegrenzer zulässt.

      Warum hast du numerische Werte überhaupt als Strings im JSON? Die Identifier (vor den :) müssen Strings sein, aber die Werte nach den [ nicht. Das ist auch valides JSON:

      {"0":[347,{"1":[10,null]}],"1":[344,{"1":[20,"1"],"2":[30,null]}],"3":[338,{"1":[30,null]}]}
      

      Kwakoni Yiquan

      --
      Ad astra per aspera
      1. Hallo Gunnar,

        Warum hast du numerische Werte überhaupt als Strings im JSON?…

        das ist mir gar nicht aufgefallen. Ich hatte die Werte unbehandelt (Asche auf mein Haupt) aus der DB im Array gespeichert. Da die Werte dort als INT gespeichert sind, wäre ich eigentlich davon ausgegangen, dass sie auch als INT "herausgeholt" werden. Offensichtlich ist das nicht der Fall. Es handelt sich noch um ein älteres Script ohne Prepared Statements. Ich behandle die Werte jetzt mit (int) nach.

        Gruß Nico

        1. Moin Nico,

          Warum hast du numerische Werte überhaupt als Strings im JSON?…

          das ist mir gar nicht aufgefallen.

          Naja, es ist schon ein Unterschied, ob Dein JSON so …

          {"0": "wert1", "1": "zwei" }
          

          … oder so aussieht:

          ["wert1", "zwei"]
          

          Ich hatte die Werte unbehandelt (Asche auf mein Haupt) aus der DB im Array gespeichert. Da die Werte dort als INT gespeichert sind, wäre ich eigentlich davon ausgegangen, dass sie auch als INT "herausgeholt" werden.

          Welchen Typ haben denn die betreffenden Tabellenspalten? Das spielt auch eine Rolle, denn eine '1' als VARCHAR ist eben ein String, während eine Spalte des Typs INTEGER wirklich nur Zahlen enthalten kann.

          Offensichtlich ist das nicht der Fall. Es handelt sich noch um ein älteres Script ohne Prepared Statements.

          Die Art der Statements hat nichts mit dem Speichern der Daten zu tun.

          Viele Grüße
          Robert

          1. Hallo Robert,

            Welchen Typ haben denn die betreffenden Tabellenspalten? Das spielt auch eine Rolle, denn eine '1' als VARCHAR ist eben ein String, während eine Spalte des Typs INTEGER wirklich nur Zahlen enthalten kann.

            Es handelt sich um INTs, bzw. um TINYINTs und SMALLINTs.

            Naja, es ist schon ein Unterschied, ob Dein JSON so …

            {"0": "wert1", "1": "zwei" }
            

            … oder so aussieht:

            ["wert1", "zwei"]
            

            Ja, das beschäftigt mich auch noch, da ein paar Folgeprobleme aufgetaucht sind. Ich hab offensichtlich noch etwas Nachholbedarf, was den Aufbau von JSON und die Rück-Überführung in ein Array bzw. Objekt angeht.

            Ich würde hierzu mal in Kürze einen neuen Beitrag aufmachen. Oder direkt hier? Das ursprüngliche Problem mit dem Kontextwechsel war ja eigentich gelöst.

            Schöne Grüße

            Nico

            1. Hallo

              Ja, das beschäftigt mich auch noch, da ein paar Folgeprobleme aufgetaucht sind. Ich hab offensichtlich noch etwas Nachholbedarf, was den Aufbau von JSON und die Rück-Überführung in ein Array bzw. Objekt angeht.

              Ich würde hierzu mal in Kürze einen neuen Beitrag aufmachen. Oder direkt hier? Das ursprüngliche Problem mit dem Kontextwechsel war ja eigentich gelöst.

              Mache für jeweils ein abgrenzbares Problem auch jeweils einen eigenen Thread auf. Bei zusammenhängenden Problemen kannst du natürlich auch in einem Thread bleiben. Wenn die Zusammenhänge aber nur lose sind, ist ein eigener Thread einfach übersichtlicher. Um von einem Thema auf ein anderes zu verweisen und Kontexte herzustellen, gibt es immer noch das, was Hypertext ausmacht, nämlich einen Link. 😉

              Tschö, Auge

              --
              „Habe ich mir das nur eingebildet, oder kann der kleine Hund wirklich sprechen?“ fragte Schnapper. „Er behauptet, nicht dazu imstande zu sein“ erwiderte Victor. Schnapper zögerte (…) „Nun …“ sagte er schließlich, „ich schätze, er muss es am besten wissen.“ Terry Prattchett, Voll im Bilde
    3. Hallo Nico R.,

      zum Thema „wie vermeide ich das ' Zeichen“ hätte ich diese Anmerkung:

      json_encode($toreArray, JSON_HEX_APOS)
      

      codiert Apostrophe automatisch als \u0027. Das Anführungszeichen " wird von json_encode automatisch als " escaped.

      Es gibt noch eine andere Alternative:

      <script type="text/plain" id="objekt_1">
        <?=htmlspecialchars(json_encode($toreArray))?>
      </script>
      

      und dann später, wo man es braucht:

      let toreArrayDB = document.getElementById("objekt_1").textContent;
      

      type="text/plain" ist nicht Vorschrift, es kann irgendwas sein. Solange es kein vorgegebener Typ ist (wie text/javascript, module oder importmap), repräsentiert so ein script-Element für den Browser einen Datenblock, den er nicht zu interpretieren hat.

      Rolf

      --
      sumpsi - posui - obstruxi
      1. @@Rolf B

        Es gibt noch eine andere Alternative:

        <script type="text/plain" id="objekt_1">
          <?=htmlspecialchars(json_encode($toreArray))?>
        </script>
        

        […] type="text/plain" ist nicht Vorschrift, es kann irgendwas sein.

        Nö, es sollte das sein, was für JSON vorgesehen ist: application/json.

        So mache ich’s auch bei den CSSBattle daily targets. Und auch bei den CSSBattle records.

        Die JSON-Daten in <script id="daily-targets" type="application/json"> im HTML-Panel, das HTML-Template im JavaScript-Panel. Verkehrte Welt?

        Kwakoni Yiquan

        --
        Ad astra per aspera
      2. Hallo Rolf,

        die Frage lag mir schon auf der Zunge.

        json_encode($toreArray, JSON_HEX_APOS)
        

        codiert Apostrophe automatisch als \u0027. Das Anführungszeichen " wird von json_encode automatisch als " escaped.

        Hat im Test funktioniert 👍

        Gruß Nico