Objekt mit boolean Attribute per $.ajax senden

Sonntag, 24. Juli, 2016

Ich habe eine kleine PHP-Applikation, die liest Metadaten aus einem JSON-File.
Diese Daten schreibt PHP-Code in ein Html-Dokument als Javascript-Objekt, damit diese in der Seite verfügbar sind.

echo 'var aMetadata=' . json_encode($o->aMetadata, JSON_PRETTY_PRINT) .';';

Wenn ich im Formular die Daten bearbeite und mein aktualisiertes Javascript ans PHP zurücksende, dann in der Form:

   var aMetadata={'title': 'Hello world' }

    $.ajax({
        type: "POST",
        url: sSaveUrl,
        data: {
            function: "setMetadata", 
            value: aMetadata, // <<<<< meine Metadaten
        }
    }).done(function () {
        // ...
    });

Auf Seite PHP wurde $_POST[”value”] der Methode setMetadata() übergeben:

    public function setMetadata($aNewMetadata) {
        if(!is_array($aNewMetadata)){
            echo "ERROR: not an array";
            return false;
        }
        $this->aMetadata=$aNewMetadata;
        return $this->saveMetadata();
    }

Das klappt soweit, bis … ja bis einmal ein boolean Wert übergeben werden soll. Es werden true/ false Werte als Strings in Form von “true”/ “false” vom $.ajax data-Wert gesendet, wenn man das Objekt direkt übergibt. Dann kann schonmal fies werden, wenn lauter korrupte Datensätze entstehen.

Abhilfe: Man muss das Objekt vor dem Absenden umwandeln. Die Lösung besteht somit besteht in 2 Teilen: einmal im Javascript das Objekt in einen String umwandeln…

   var aMetadata={'title': 'Hello world', 'hasdata': false }

    $.ajax({
        type: "POST",
        url: sSaveUrl,
        data: {
            function: "setMetadata", 
            value: JSON.stringify(aMetadata), // <<<<< Object in einen String umwandeln
        }
    }).done(function () {
        // ...
    });

… und auf der Seite PHP den String zurückumwandeln. Dazu nehme man die Funktion json_decode und übergebe neben den Rohdaten den 2. Parameter true, damit ein Hash entsteht.

    /**
     * set new metadata array
     * @param array $aNewMetadata  new metadata as array or string (sent with JSON.stringify(aMetadata) in JS)
     * @return boolean
     */
    public function setMetadata($aNewMetadata) {
        // wenn es ein String ist, dann zurueckumwandeln
        if (is_string($aNewMetadata)){
            $aNewMetadata=json_decode($aNewMetadata, 1);
        }
        if(!is_array($aNewMetadata)){
            echo "ERROR: no valid json or not an array";
            return false;
        }
        $this->aMetadata=$aNewMetadata;
        return $this->saveMetadata();
    }

weiterführende Links:

  1. php.net: json_encode
  2. php.net: json_decode
  3. developer.mozilla.org: JSON.stringify (en)