mixmastertobsi: AJAX - JSON.stringify - Sonderzeichen

Hallo,

mit JSON.stringify übergebe ich einen array an PHP. Funktioniert auch soweit, nur mit einem Problem. Wenn im Text ein Undzeichen vorkommt, werden die Daten nicht korrekt übertragen. Meine Frage - wie sollte ich hier das "Undzeichen" noch codieren? Weiteres Problem ist das Plus-Zeichen, wie codiere ich dieses, damit es bei der Übergabe kein Leerzeichen wird?

  1. Hallo mixmastertobsi,

    Wenn im Text ein Undzeichen vorkommt, werden die Daten nicht korrekt übertragen. Meine Frage - wie sollte ich hier das "Undzeichen" noch codieren? Weiteres Problem ist das Plus-Zeichen, wie codiere ich dieses, damit es bei der Übergabe kein Leerzeichen wird?

    Kontext beachten: einmal durch encodeURIComponent schicken.

    LG,
    CK

    1. Hallo und Danke!

      encodeURIComponent hatte ich bereits probiert und es funktioniert auch mit dem Und-Zeichen. Das Plus-Zeichen wird leider aber dennoch zum Leerzeichen. Was kann/muss ich hier machen?

      1. Hallo mixmastertobsi,

        encodeURIComponent hatte ich bereits probiert und es funktioniert auch mit dem Und-Zeichen. Das Plus-Zeichen wird leider aber dennoch zum Leerzeichen. Was kann/muss ich hier machen?

        Dann machst du noch etwas anderes falsch. Für mehr Analyse ist mehr Code notwendig. Wie du an diesen Fehler herangehen kannst hat dir @dedlfix ja schon erklärt.

        LG,
        CK

  2. Hallo,

    mit JSON.stringify übergebe ich einen array an PHP. Funktioniert auch soweit, nur mit einem Problem. Wenn im Text ein Undzeichen vorkommt, werden die Daten nicht korrekt übertragen.

    Glaub ich Dir nicht, wie kommst Du darauf, hast Du geprüft wie der String aussieht der übertragen wird? Die Console ist Dein Freund.

    Meine Frage - wie sollte ich hier das "Undzeichen" noch codieren? Weiteres Problem ist das Plus-Zeichen, wie codiere ich dieses, damit es bei der Übergabe kein Leerzeichen wird?

    Ich vermute, dass der serverseitige Parser nicht das macht was Du erwartest. Also prüfen.

    1. Tach!

      Wenn im Text ein Undzeichen vorkommt, werden die Daten nicht korrekt übertragen.

      Glaub ich Dir nicht, wie kommst Du darauf, hast Du geprüft wie der String aussieht der übertragen wird? Die Console ist Dein Freund.

      Das zu prüfen ist keine schlechte Idee. Bei einer Verarbeitungskette sollte man die Daten an allen Stellen prüfen, durch die sie laufen.

      Ich vermute, dass der serverseitige Parser nicht das macht was Du erwartest. Also prüfen.

      Das ist alles Standard-Krams. Sowohl der Parser, der die Daten in $_GET/$_POST bereitstellt, als auch der JSON-Parser. Die werden nicht defekt sein, ohne dass es bereits irgendwer bemerkt und gefixt hätte, noch dazu bei solchen alltäglichen Zeichen.

      Hier käme nun die Prüfung ins Spiel. Wo sind die Daten kaputtgegangen? Diese wird ergeben, dass die Daten bereits in $_GET/$_POST in veränderter Form enthalten sind. Das lässt sich zumindest aus der Problembeschreibung vermuten. Ist das der Fall, ist die Übertragungsstrecke der Übeltäter. Oder die Vorbereitung der Daten für die Übertragung.

      dedlfix.

      1. Tach!

        Wenn im Text ein Undzeichen vorkommt, werden die Daten nicht korrekt übertragen.

        Glaub ich Dir nicht, wie kommst Du darauf, hast Du geprüft wie der String aussieht der übertragen wird? Die Console ist Dein Freund.

        Das zu prüfen ist keine schlechte Idee. Bei einer Verarbeitungskette sollte man die Daten an allen Stellen prüfen, durch die sie laufen.

        Richtig! Und was hat Deine Prüfung ergeben?

        1. Hallo,

          Und was hat Deine Prüfung ergeben?

          zuwenig Infos vorhanden.

          Gruß
          Kalk

      2. Ich vermute, dass der serverseitige Parser nicht das macht was Du erwartest. Also prüfen.

        Das ist alles Standard-Krams.

        So!? Wie verarbeitet denn der PHP-Parser einen Content-Type: application/json? Falls der überhaupt gesendet wurde -- das wäre die nächste Frage.

        1. Tach!

          Ich vermute, dass der serverseitige Parser nicht das macht was Du erwartest. Also prüfen.

          Das ist alles Standard-Krams.

          So!? Wie verarbeitet denn der PHP-Parser einen Content-Type: application/json? Falls der überhaupt gesendet wurde -- das wäre die nächste Frage.

          Welchen PHP-Parser meinst du? Die Funktion json_decode() nimmt einen String entgegen. Ein Content-Type spielt dabei keine Rolle. Da muss nur ein gültiger JSON-String übergeben werden.

          Einen Request mit anderen Content-Types als den üblichen für GET und POST zu schicken, bedeutet Handarbeit beim Extrahieren, weil das dann nicht PHP übernimmt und zugriffsfertig in $_GET/$_POST bereitstellt. Im Falle eines application/json würde man wohl keine Kodierung der Nutzdaten vornehmen, die Probleme bei Nicht-Buchstaben verusacht. Da kann man sich nun raussuchen, was das kleinere Übel ist. Vorgefertigte Dinge in PHP auf einfache Weise nutzen und dafür eine Kodierug bei Sender vornehmen, oder den korrekten Content-Type schicken und Handarbeit in PHP (was aber auch nicht allzu schwer ist).

          dedlfix.

          1. Tach!

            Ich vermute, dass der serverseitige Parser nicht das macht was Du erwartest. Also prüfen.

            Das ist alles Standard-Krams.

            So!? Wie verarbeitet denn der PHP-Parser einen Content-Type: application/json? Falls der überhaupt gesendet wurde -- das wäre die nächste Frage.

            Welchen PHP-Parser meinst du? Die Funktion json_decode() nimmt einen String entgegen. Ein Content-Type spielt dabei keine Rolle. Da muss nur ein gültiger JSON-String übergeben werden.

            Guck mal

            Mein Parser kann mit dem Content-Type umghen, die Response sieht dann so aus:

            $VAR1 = bless( {
                             'CONTENT_TYPE_ORIGIN' => 'application/json',
                             'rawdata' => '',
                             'STDIN' => bless( \*Symbol::GEN2, 'IO::String' ),
                             'CONTENT_TYPE' => 'application/json',
                             'eav' => {},
                             'CONTENT_LENGTH' => 47,
                             'param' => {
                                          'foo' => 1
                                        },
                             'QUERY_STRING' => '',
                             'json' => {
                                         'param' => $VAR1->{'param'},
                                         'arr' => [
                                                    'foo',
                                                    'bar+',
                                                    'baz&'
                                                  ]
                                       }
                           }, 'xCGI' );
            

            Nur mal als Beispiel. Dass '&' und '+' u.a. Zeichen nicht korrekt übertragen werden, halt ich fürn Gerücht. Selbst wenn der Parser den Content-Type nicht kennt, sollte der Orininal-JSON-String in STDIN zu finden sein bei einem POST.

            1. Mein Parser kann mit dem Content-Type umghen

              In PHP ein Einzeiler:

              $json = json_decode(file_get_contents('php://input'));
              

              In Perl geht es mit Sicherheit genauso bündig.

              Nur mal als Beispiel. Dass '&' und '+' u.a. Zeichen nicht korrekt übertragen werden, halt ich fürn Gerücht.

              Du gibst dir einfach nur keine Mühe die Symptome zu interpretieren.

              1. Hallo 1unitedpower,

                Mein Parser kann mit dem Content-Type umghen In PHP ein Einzeiler:

                $json = json_decode(file_get_contents('php://input'));
                

                Das bekommt man auch in Perl als Ein-, nagut Zweizeiler, hin ;-)

                use JSON;
                my $json = decode_json(<STDIN>);
                

                LG,
                CK

                1. Das bekommt man auch in Perl als Ein-, nagut Zweizeiler, hin ;-)

                  Das ist mir nach abschicken meines Postings auch aufgefallen, deswegen habe mich sofort ergänzt ;)

                  1. Hallo 1unitedpower,

                    Das bekommt man auch in Perl als Ein-, nagut Zweizeiler, hin ;-)

                    Das ist mir nach abschicken meines Postings auch aufgefallen, deswegen habe mich sofort ergänzt ;)

                    Zu spät, zu spät! 😂

                    LG,
                    CK

                    1. @@Christian Kruse

                      Zu spät, zu spät! 😂

                      Das Bemerkenswerte daran: das Durchschnittsalter der heutigen Fans der „besten Band der Welt“ ist deutlich jünger als dieses Lied.

                      LLAP 🖖

                      --
                      “The best way to help people learn: answer their coding question an hour later, they’ll have likely figured it out by then.” —Todd Motto
                      Selfcode: sh:) fo:} ch:? rl:) br:> n4:& va:| de:> zu:} fl:{ ss:| ls:# js:|
                      1. Hallo,

                        Das Bemerkenswerte daran: das Durchschnittsalter der heutigen Fans der „besten Band der Welt“ ist deutlich jünger als dieses Lied.

                        Bist du sicher, dass es sich um Fäns der Band handelt und nicht um Fäns dieses Liedes, das sie dann irgendeiner Coverbänd zuordnen?

                        Gruß
                        Kalk

                      2. Hallo Gunnar Bittersmann,

                        Das Bemerkenswerte daran: das Durchschnittsalter der heutigen Fans der „besten Band der Welt“ ist deutlich jünger als dieses Lied.

                        Ein Alter (im Sinne von oben) kann nicht jünger sein. Ebenso wie eine Temperatur nicht kälter sein kann ;-)

                        Bis demnächst
                        Matthias

                        --
                        Dieses Forum nutzt Markdown. Im Wiki erhalten Sie Hilfe bei der Formatierung Ihrer Beiträge.
                        1. @@Matthias Apsel

                          Ein Alter (im Sinne von oben) kann nicht jünger sein. Ebenso wie eine Temperatur nicht kälter sein kann ;-)

                          Grmpf. ;-)

                          LLAP 🖖

                          --
                          “The best way to help people learn: answer their coding question an hour later, they’ll have likely figured it out by then.” —Todd Motto
                          Selfcode: sh:) fo:} ch:? rl:) br:> n4:& va:| de:> zu:} fl:{ ss:| ls:# js:|
                2. Hallo 1unitedpower,

                  Mein Parser kann mit dem Content-Type umghen In PHP ein Einzeiler:

                  $json = json_decode(file_get_contents('php://input'));
                  

                  Das bekommt man auch in Perl als Ein-, nagut Zweizeiler, hin ;-)

                  use JSON;
                  my $json = decode_json(<STDIN>);
                  

                  Nein so einfach ist das nicht, weil STDIN bereits vom Parser ausgelesen wurde in dem Moment wenn CONTENT_LENGTH gesetzt ist.

                  Zum Problem nachstellen brauchts schon ein bischen mehr Überlegungen.

              2. Mein Parser kann mit dem Content-Type umghen In PHP ein Einzeiler:

                $json = json_decode(file_get_contents('php://input'));
                

                In Perl geht es mit Sicherheit genauso bündig.

                Nur mal als Beispiel. Dass '&' und '+' u.a. Zeichen nicht korrekt übertragen werden, halt ich fürn Gerücht.

                Du gibst dir einfach nur keine Mühe die Symptome zu interpretieren.

                Ach was, jetzt wird interessant. Schauen wir doch mal:

                Wenn im Text ein Undzeichen vorkommt, werden die Daten nicht korrekt übertragen.

                Das ist kein Symtom sondern eine Behauptung. Und das hier

                Weiteres Problem ist das Plus-Zeichen, wie codiere ich dieses, damit es bei der Übergabe kein Leerzeichen wird?

                Ist nicht einmal eine Problembeschreibung. Das haben meine Bemühungen ergeben und außerdem hab ich Euch eine Testumgebung bereitgestellt: hier

                Und dann kommt Du und behauptest, ich würde mir keine Mühe geben!? Das ist unverschämt!

          2. hi,

            Welchen PHP-Parser meinst du? Die Funktion json_decode() nimmt einen String entgegen. Ein Content-Type spielt dabei keine Rolle. Da muss nur ein gültiger JSON-String übergeben werden.

            Je nach gesendetem Content-Type stellt der Parser auch in PHP die Daten wieder her für einen wahlfreien Zugriff. Üblich sind 'application/x-www-form-urlencoded' und 'multipart/form-data' und der wahlfreie Zugriff ergibt sich nach dem Parsen über $_POST//$_GET je nachdem wo die Daten herkommen. Auf jeden Fall fragt auch in PHP der Parser den gesendeten Content-Type ab, denn er muss ja wissen nach welchem Algorithmus die Daten wiederhergestellt werden sollen.

            Eine Überlegung, dass ebendieser Parser bei einem gesendeten Content-Type: application/json die wiederhergestellte Datenstruktur direkt ins $_POST Array schreibt ist also naheliegend, aber ob er das wirklich macht, kann ich momentan nicht sagen (das wäre zu prüfen). Es wäre ein impliziter Aufruf $_POST = json_decode(STDIN); um das mal so zu formulieren.

            Schön wär's ja!

            1. Tach!

              Je nach gesendetem Content-Type stellt der Parser auch in PHP die Daten wieder her für einen wahlfreien Zugriff. Üblich sind 'application/x-www-form-urlencoded' und 'multipart/form-data' und der wahlfreie Zugriff ergibt sich nach dem Parsen über $_POST//$_GET je nachdem wo die Daten herkommen. Auf jeden Fall fragt auch in PHP der Parser den gesendeten Content-Type ab, denn er muss ja wissen nach welchem Algorithmus die Daten wiederhergestellt werden sollen.

              Wenn die Daten an der Quelle nicht richtig eingepackt wurden, im Sinne der beiden Content-Typen, dann treten die vom OP beobachten Symptome auf.

              Eine Überlegung, dass ebendieser Parser bei einem gesendeten Content-Type: application/json die wiederhergestellte Datenstruktur direkt ins $_POST Array schreibt ist also naheliegend, aber ob er das wirklich macht, kann ich momentan nicht sagen (das wäre zu prüfen).

              Macht er nicht. Wenn man die Daten in $_POST haben möchte, muss man die beiden genannten Content-Typen verwenden. PHP hat $_GET/$_POST zu einer Zeit implementiert, als alle Browser noch brav nur Formulare schicken konnten. Die beiden Arrays beziehen sich nur auf das method-Attribut von Formularen und behandelt die Daten gemäß den von den Browsern dafür verwendeten Content-Typen. Dass man seit einiger Zeit Ajax-Requests mit anderen Content-Typen versenden kann, ist in der Hinsicht an PHP vorübergegangen. Das heißt, $_GET und $_POST werden dann nicht befüllt.

              Es wäre ein impliziter Aufruf $_POST = json_decode(STDIN); um das mal so zu formulieren.

              Das passiert nicht. Man kann sich bei PHP entweder die Rohdaten direkt aus dem Request holen (das ist für PHP eher unüblich) oder man holt holt sich die dekodierten Daten aus $_POST, wenn es Formulardaten waren.

              Im Falle des OP waren es offensichtlich keine Rohdaten. Denn dann wäre in aller Regel kein Dekodierfehler nach den beschriebenen Symptomen aufgetreten. Also wird er sie wohl aus $_POST abholen und an der Quelle als application/x-www-form-urlencoded (Standard-Wert für Ajax) versenden. Dabei wird er nicht beachtet haben, dass sie kodiert werden müssen. Und dann tritt das auf, was er beschrieben hat.

              dedlfix.

              1. Im Falle des OP waren es offensichtlich keine Rohdaten. Denn dann wäre in aller Regel kein Dekodierfehler nach den beschriebenen Symptomen aufgetreten. Also wird er sie wohl aus $_POST abholen und an der Quelle als application/x-www-form-urlencoded (Standard-Wert für Ajax) versenden. Dabei wird er nicht beachtet haben, dass sie kodiert werden müssen. Und dann tritt das auf, was er beschrieben hat.

                Ne, ich kann das beim Besten Willen nicht nachvollziehen. Da muss er schon irgenwas ganz Dummes gemacht haben, was an jeglichen Standards vorbeigegangen ist. Du kannst das gerne mal etwas näher beschreiben, falls Du den seine Probleme nachstellen konntest.

                Im Übrigen:

                <?php
                header('Content-Type: text/plain;Charset=UTF-8');
                $_POST = json_decode(file_get_contents('php://input'));
                print_r($_POST);
                ?>
                

                Liefert mir exakt das, was ich gesendet habe:

                stdClass Object
                (
                    [param] => stdClass Object
                        (
                            [foo] => 1
                        )
                
                    [arr] => Array
                        (
                            [0] => foo
                            [1] => bar+
                            [2] => baz&
                        )
                
                )
                

                EingeJSON't mit Perl:

                my $hunt = {
                    arr   => ['foo','bar+','baz&'],
                    param => {foo => 1} 
                };
                my $jsonstr = to_json($hunt);
                
                my $r = HTTPRequest->common(
                    host           => 'rolfrost.de',
                    method         => 'POST',
                    uri            => '/p.php',
                    content        => $jsonstr,
                ) or die $@;
                
                
                print $r->response_body;
                

                ohne dass es nur ansatzweise irgendwelche Kodierungsprobleme gibt. Du kannst das selber testen p.php ist online.

                1. Tach!

                  Ne, ich kann das beim Besten Willen nicht nachvollziehen. Da muss er schon irgenwas ganz Dummes gemacht haben, was an jeglichen Standards vorbeigegangen ist. Du kannst das gerne mal etwas näher beschreiben, falls Du den seine Probleme nachstellen konntest.

                  Erstell einen Ajax-Request ohne Content-Type-Angabe oder nimm den Standard-Wert application/x-www-form-urlencoded. Sende als Payload sowas wie data=... und da dann ohne Prozentkodierung ein paar Daten mit den Zeichen & und +.

                  Lass diese am Ziel dekodieren. Das & wird als Trennzeichen zwischen Feldnamen (wie das data hier) erkennt und an der Stelle geht der Rest verloren, weil er am Ziel nicht in $_POST['data'] auftaucht. +-Zeichen werden zu Space dekodiert.

                  <?php
                  header('Content-Type: text/plain;Charset=UTF-8');
                  $_POST = json_decode(file_get_contents('php://input'));
                  print_r($_POST);
                  ?>
                  

                  Die Zuweisung an $_POST ist Quatsch, so funktioniert PHP nicht. Wenn man sich die Daten schon selbst aus stdin holt, kann man sich gleich in einer eigenen Variable ablegen und muss nicht $_POST zumüllen.

                  dedlfix.

                  1. Tach!

                    Ne, ich kann das beim Besten Willen nicht nachvollziehen. Da muss er schon irgenwas ganz Dummes gemacht haben, was an jeglichen Standards vorbeigegangen ist. Du kannst das gerne mal etwas näher beschreiben, falls Du den seine Probleme nachstellen konntest.

                    Erstell einen Ajax-Request ohne Content-Type-Angabe oder nimm den Standard-Wert application/x-www-form-urlencoded. Sende als Payload sowas wie data=...

                    Aha, auf so eine Idee muss man ja erstmal kommen, das ging aus der Problembeschreibung leider nicht hervor.

                    Die Zuweisung an $_POST ist Quatsch,

                    Du hast ja auch gar nicht verstanden, was ich Dir damit zeigen wollte: Eine implizite Zuweisung der gesendeten Datenstruktur abhängig vom Content-Type. So siehst Du den Dump auch nur dann, wenn der Content-Type zum Inhalt passend ist:

                    my $r = HTTPRequest->common(
                        host           => 'rolfrost.de',
                        method         => 'POST',
                        uri            => '/p.php',
                        #'Content-Type' => 'application/x-www-form-urlencoded',
                        'Content-Type' => 'application/json',
                        #content        => "data=1&1+", 
                        content        => q({"param":{"foo":1},"arr":["foo","bar+","baz&"]})
                    ) or die $@;
                    

                    is online.

                    1. Tach!

                      Ne, ich kann das beim Besten Willen nicht nachvollziehen. Da muss er schon irgenwas ganz Dummes gemacht haben, was an jeglichen Standards vorbeigegangen ist. Du kannst das gerne mal etwas näher beschreiben, falls Du den seine Probleme nachstellen konntest.

                      Erstell einen Ajax-Request ohne Content-Type-Angabe oder nimm den Standard-Wert application/x-www-form-urlencoded. Sende als Payload sowas wie data=...

                      Aha, auf so eine Idee muss man ja erstmal kommen, das ging aus der Problembeschreibung leider nicht hervor.

                      Und das geht am Thema JSON auch völlig vorbei, es macht überhaupt keinen Sinn einen JSON so verwenden zu wollen!

                      Die Zuweisung an $_POST ist Quatsch,

                      Du hast ja auch gar nicht verstanden, was ich Dir damit zeigen wollte:

                      Ist vielleicht auch besser so.

                      1. Tach!

                        Erstell einen Ajax-Request ohne Content-Type-Angabe oder nimm den Standard-Wert application/x-www-form-urlencoded. Sende als Payload sowas wie data=...

                        Aha, auf so eine Idee muss man ja erstmal kommen, das ging aus der Problembeschreibung leider nicht hervor.

                        Das ist aber eine der üblichen Verwendungen von Ajax-Requests. Auf diese Weise können die Daten in PHP einfach aus $_POST geholt werden, ohne dass man php://input bemühen muss.

                        Und das geht am Thema JSON auch völlig vorbei, es macht überhaupt keinen Sinn einen JSON so verwenden zu wollen!

                        Das würde mit allen Daten passieren, die so transportiert werden. Dass es diesmal mit JSON serialisierte getroffen hat, ist nebensächlich. Dass es andere Möglichkeiten gibt, JSON-Daten zu übertragen, als application/x-www-form-urlencoded, macht eine solche Übertragung nicht unbedingt sinnlos. Der JSON-String ist ein String wie andere Strings auch. Und wenn das Backend so aufgebaut ist, dass es damit funktioniert, warum nicht? Alles in allem ist das noch nicht unnötig kompliziert.

                        Die Zuweisung an $_POST ist Quatsch,

                        Du hast ja auch gar nicht verstanden, was ich Dir damit zeigen wollte:

                        Ist vielleicht auch besser so.

                        Weißt du, ich habe schon länger aufgegeben, verstehen zu wollen, was du sagen möchtest. Oft habe ich versucht, Fragen zu deinen Aussagen zu stellen. Meist hast du sie unbeantwortet gelassen und stattdessen irgendwas anderes erzählt, gern war das Perl-Code, nach dem keiner gefragt hat. Und diesmal war es auch nicht anders.

                        dedlfix.

                        1. Tach!

                          Erstell einen Ajax-Request ohne Content-Type-Angabe oder nimm den Standard-Wert application/x-www-form-urlencoded. Sende als Payload sowas wie data=...

                          Aha, auf so eine Idee muss man ja erstmal kommen, das ging aus der Problembeschreibung leider nicht hervor.

                          Das ist aber eine der üblichen Verwendungen von Ajax-Requests. Auf diese Weise können die Daten in PHP einfach aus $_POST geholt werden, ohne dass man php://input bemühen muss.

                          Und das geht am Thema JSON auch völlig vorbei, es macht überhaupt keinen Sinn einen JSON so verwenden zu wollen!

                          Das würde mit allen Daten passieren, die so transportiert werden.

                          Nein eben nicht! Wenn nämlich der Content-Type 'application/x-www-form-urlencoded' gesendet wid, arbeitet der Parser entsprechend und deutet & als Trennzeichen sowie + als Leerzeichen (siehe auch RFC 3986). Somit ist es nicht nur unsinnig sondern auch falsch ein data=$json zu senden und dann in das $_POST Array zu greifen.

                          Wenn das bei Dir so üblich ist, hast Du den Sinn des Request-Content-Type nicht verstanden, aber diesen Eindruck hatte ich ja gestern schon.

                          Also entweder 'application/x-www-form-urlencoded' ODER 'application/json' senden und selbstverständlich muss das serverseitige Parsen dem im Request mitgegebenen Content-Type entsprechend erfolgen. Andererseits ist es auch unsinnig, ein Percent-Encoding gem. RFC 3986 in JSON-Strings anzuwenden.

                          Weil JSON nicht eine Componente von 'application/x-www-form-urlencoded' ist sondern einen eigenen Content-Type darstellt!

                          PS: Die ++Bewertung Deiner Beiträge sagt mir, dass hier einiges im Argen liegt.

                          1. Hallo pl,

                            Nein eben nicht! Wenn nämlich der Content-Type 'application/x-www-form-urlencoded' gesendet wid, arbeitet der Parser entsprechend und deutet & als Trennzeichen sowie + als Leerzeichen (siehe auch RFC 3986).

                            Gratuliere, du bist gerade an dem Punkt angekommen, an dem wir gestern schon waren. Wenn du dir ein bisschen Mühe gibst, dann kommst du noch drauf, warum das encodeURIComponent nötig ist und was das bewirkt.

                            Somit ist es nicht nur unsinnig sondern auch falsch ein data=$json zu senden und dann in das $_POST Array zu greifen.

                            Es ist die kreative Verwendung bestehender Technik und damit durchaus sinnvoll: man erspart sich zusätzliche Komplexität durch mehr Code.

                            PS: Die ++Bewertung Deiner Beiträge sagt mir, dass hier einiges im Argen liegt.

                            Jup. Mit scharfem Nachdenken kommst du drauf! Ich glaube an dich!

                            LG,
                            CK

                          2. Tach!

                            Das würde mit allen Daten passieren, die so transportiert werden.

                            Nein eben nicht! Wenn nämlich der Content-Type 'application/x-www-form-urlencoded' gesendet wid, arbeitet der Parser entsprechend und deutet & als Trennzeichen sowie + als Leerzeichen (siehe auch RFC 3986). Somit ist es nicht nur unsinnig sondern auch falsch ein data=$json zu senden und dann in das $_POST Array zu greifen.

                            Und was daran ist "Nein eben nicht!"? Genau das ist doch das Problem, das das zu den Symptomen des OP passt. Also keinen Content-Typ angegeben oder den Default-Wert 'application/x-www-form-urlencoded' und die Daten vergessen zu maskieren. Das passiert mit jeglichen Daten, die so unmaskiert transportiert werden, nicht nur mit JSON.

                            Wenn das Nein vielmehr heißen sollte, man könne im Falle von JSON einen anderen Content-Type nehmen - ja klar, ändert aber nichts daran, dass man bei 'application/x-www-form-urlencoded' maskieren muss.

                            Trotzdem ist es nicht generell falsch, data=$json zu senden, es muss eben nur data=encodeURIComponent($json) draus gemacht werden. Solange der serverseitige Prozess das genauso erwartet, und wenn man keine öffentliche API schreibt, sondern nur die eigene Anwendung das so verwendet, sehe ich auch keinen Grund, das unnötig hübsch zu gestalten.

                            Wenn das bei Dir so üblich ist, hast Du den Sinn des Request-Content-Type nicht verstanden, aber diesen Eindruck hatte ich ja gestern schon.

                            Ich habe das schon verstanden.

                            Also entweder 'application/x-www-form-urlencoded' ODER 'application/json' senden und selbstverständlich muss das serverseitige Parsen dem im Request mitgegebenen Content-Type entsprechend erfolgen. Andererseits ist es auch unsinnig, ein Percent-Encoding gem. RFC 3986 in JSON-Strings anzuwenden.

                            Weil JSON nicht eine Componente von 'application/x-www-form-urlencoded' ist sondern einen eigenen Content-Type darstellt!

                            JSON ist nicht nur application/json, JSON ist auch text/plain oder auch binary/octet-stream. Oder anders gesagt, man kann JSON auch einfach nur als eine beliebige Zeichenfolge betrachten und sie zum Übertragen in einen anderen Container stecken. Das ist nicht falsch, muss sich aber wie jede andere beliebige Zeichenfolge an die Regeln des Containers halten.

                            Man könnte beispielsweise zusätzlich zum JSON auch noch andere Daten mitsenden wollen. Die würde man bei application/json nicht übertragen bekommen (höchstens als Header-Zeilen), ohne dass man sie in das JSON einbaut. Das kann aber je nach Anwendungsfall auch ungewünscht sein. Wenn z.B. der JSON-Teil einen Datensatz darstellt, den man nicht mit den anderen Daten vermischen möchte, dann kann man beispielsweise application/x-www-form-urlencoded und data=encodeURIComponent($json)&anderes=encodeURIComponent($anderes) verwenden.

                            PS: Die ++Bewertung Deiner Beiträge sagt mir, dass hier einiges im Argen liegt.

                            Das glaube ich auch. Zum Beispiel, dass du dich zu sehr in deiner eigenen Welt mit Perl, EAV und Binärdatenübertragung eingekuschelt hast, und so nicht mehr siehst, dass es noch jede Menge anderer Wege gibt.

                            dedlfix.

  3. Hallo,

    mit JSON.stringify übergebe ich einen array an PHP. Funktioniert auch soweit, nur mit einem Problem. Wenn im Text ein Undzeichen vorkommt, werden die Daten nicht korrekt übertragen. Meine Frage - wie sollte ich hier das "Undzeichen" noch codieren? Weiteres Problem ist das Plus-Zeichen, wie codiere ich dieses, damit es bei der Übergabe kein Leerzeichen wird?

    Extra für Dich und aus diesem Anlass siehe: Artikel -- leicht verständlich erklärt.

    MfG

    1. Tach!

      mit JSON.stringify übergebe ich einen array an PHP. Funktioniert auch soweit, nur mit einem Problem. Wenn im Text ein Undzeichen vorkommt, werden die Daten nicht korrekt übertragen. Meine Frage - wie sollte ich hier das "Undzeichen" noch codieren? Weiteres Problem ist das Plus-Zeichen, wie codiere ich dieses, damit es bei der Übergabe kein Leerzeichen wird?

      Extra für Dich und aus diesem Anlass siehe: Artikel -- leicht verständlich erklärt.

      Dann auch von mir der Versuch einer kompletten Erklärung.

      Vermutlich ist beim OP ein Stück Javascript nach folgendem Prinzip im Einsatz:

      var json = JSON.stringify(some_data_object_or_array);
      
      var xmlhttp = new XMLHttpRequest();
      xmlhttp.open("POST", url);
      xmlhttp.send("data=" + json);
      

      Nicht zu sehen ist hier, dass der Browser beim Senden an die URL den Content-Type auf den Standard-Wert "application/x-www-form-urlencoded; charset=UTF-8" setzt. Das Problem an obigem Code ist, dass der String in der Variable json Zeichen enthalten kann, die gemäß diesem Content-Type eine besondere Bedeutung haben. Das betrifft vor allem das &, welches als Parameter-Trenner verwendet wird: data=text&moredata=moretext. Es ist deshalb notwendig, dass diese Zeichen mit besonderer Bedeutung in den Nutzdaten (sprich: in dem String in der Variable json) entsprechend maskiert werden. Das kann die Funktion encodeURIComponent().

      var json = JSON.stringify(some_data_object_or_array);
      
      var xmlhttp = new XMLHttpRequest();
      xmlhttp.open("POST", url);
      xmlhttp.send("data=" + encodeURIComponent(json));
      

      So wäre es nun korrekt. Und das Prinzip betrifft alle Daten, nicht nur Strings, die zufälligerweise JSON enthalten. Hat man weitere Daten, hängt man sie nach demselben Prinzip und durch & getrennt aneinander.

      var json = JSON.stringify(some_data_object_or_array);
      
      var xmlhttp = new XMLHttpRequest();
      xmlhttp.open("POST", url);
      xmlhttp.send("data=" + encodeURIComponent(json) + "&" + "moredata=" + encodeURIComponent(moredata));
      

      (Natürlich kann man auch ... + "&moredata=" + ... schreiben, aber ich habe das & zur Verdeutlichung extra geschrieben.)

      Wenn man PHP auf der Server-Seite hat, kann man nun die Daten in $_POST entgegennehmen. PHP dekodiert die Daten selbständig gemäß dem mitgesendeten Content-Type application/x-www-form-urlencoded, man muss also nicht das Gegenstück zu encodeURIComponent() ausführen.

      <?php
      $some_data_object_or_array = json_decode($_POST['data']);
      do_something_with_moredata($_POST['moredata']);
      

      Alternativer Ansatz:

      Die oben gezeigte Methode eignet sich vor allem auch in Fällen, in denen weitere Daten neben dem JSON-Inhalt zum Server gesendet werden müssen. Ist der JSON-Inhalt hingegen die einzige Nutzlast, die zum Server übertragen werden muss, dann kann man das auch nach diesem Prinzip machen, aber man kann den JSON-Inhalt auch direkt übertragen, ohne zusätzliches data=. Man muss dazu jedoch den Content-Type anpassen.

      var json = JSON.stringify(some_data_object_or_array);
      
      var xmlhttp = new XMLHttpRequest();
      xmlhttp.open("POST", url);
      xmlhttp.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
      xmlhttp.send(json); // <- nur json, nichts weiter
      

      Auch auf der Serverseite muss man nun anders vorgehen. PHP kennt den Content-Type application/json nicht und erzeugt nun auch keine Einträge in $_POST und dergleichen. Stattdessen muss man sich den Inhalt selbst und direkt aus dem Request-Body holen. PHP stellt den unter der Pseudo-URL php://input zur Verfügung. Diese lässt sich PHP-üblich mit Filesystemfunktionen abfragen lässt.

      <?php
      $request_body = file_get_contents('php://input');
      $some_data_object_or_array = json_decode($request_body);
      

      Man kann die Angelegenheit nun noch weiter verfeinern, indem man die Request-Header nach Content-Type durchsucht (die Funktion apache_request_headers() liefert diese), und diesen auswertet, um auch andere Daten als JSON erkennen zu können. Das lohnt sich aber nicht, wenn man lediglich von seiner eigenen Website Daten erwartet. Stellt man hingegen eine öffentliche API zur Verfügung, wäre das der Weg, den Clienten mehr Freiheiten beim Datenformat zu geben.

      dedlfix.

    2. Extra für Dich und aus diesem Anlass siehe: Artikel -- leicht verständlich erklärt.

      Hab nochwas dazugeschrieben: JavaScript FormData zum Senden mehrerer Content-Types

      1. Tach!

        Extra für Dich und aus diesem Anlass siehe: Artikel -- leicht verständlich erklärt.

        Hab nochwas dazugeschrieben: JavaScript FormData zum Senden mehrerer Content-Types

        Kann man so machen, ist aber unnötig komplex. Man muss bei dieser Lösung dafür sorgen, dass ein Temp-Verzeichnis für die Datei zur Verfügung steht, das für den Webserver-Prozess schreibbar ist und dann sich durch $_FILES graben und diese Datei lesen. Wenigstens kümmert sich PHP selbständig um das Löschen der temporären Datei.

        Warum sperrst du dich eigentlich so dagegen, die Zeichenfolge, die sozusagen rein zufällig wie ein JSON-Dokument aussieht, als eine einfache Zeichenfolge zu betrachten und so zu behandeln? In Javascript nach dem JSON.stringify() und in PHP vor dem json_decode() sind es lediglich Strings, ohne dass da eine Content-Type-Information drangeschrieben steht. Nur für die Übertragung einen Heckmeck mit dem Content-Type zu veranstalten, bringt keine Punkte. Die Sachlage sähe lediglich dann anders aus, wenn anhand dieses Content-Types die weitere Verarbeitung festgelegt wird. Das scheint mir aber in dem Fall nicht gegeben zu sein.

        dedlfix.