HTTP Content-Type Header und JSON

144

Ich habe immer versucht, die meisten Eigenschaften des HTTP-Protokolls aus Angst vor dem Unbekannten nicht zu verwenden.

Ich sagte mir jedoch, dass ich heute Angst haben und absichtlich Header verwenden werde. Ich habe versucht, jsonDaten an den Browser zu senden und sie sofort zu verwenden. Wenn ich zum Beispiel eine Ajax-Handlerfunktion im Bereitschaftszustand 4 habe, die so aussieht:

function ajaxHandler(response){
    alert(response.text);
}

Und ich habe den Inhaltstyp-Header in meinem PHP-Code festgelegt:

header('Content-Type: application/json');
echo json_encode(array('text' => 'omrele'));

Warum kann ich nicht direkt über die Handlerfunktion auf die Eigenschaft zugreifen, wenn dem Browser klar mitgeteilt wird, dass es sich um eingehende Daten handelt application/json?

php_nub_qq
quelle
Wenn ich das richtig verstehe, möchten Sie es textals Javascript-Variable im Handler verwenden und nicht als Antwort? Das wäre eine sehr seltsame Funktionalität. Der json_encode erstellt auch 1 Objekt aus Ihrem PHP-Array. Wenn Sie dies in Javascript einbinden, muss es einer Variablen zugewiesen werden.
Flashin
4
Der contentType-Header dient nur zur Information. Der Browser wird das verwenden, wenn es kann, aber in diesem Fall ignorieren die Browser es einfach, weil sie normalerweise nicht wissen, was die Absicht ist. Ihre Javascript-Anwendung kann davon Gebrauch machen. Sie gehen davon aus, dass JSON präsentiert wird, damit Sie es mit dekodieren können JSON.parse(). Sie können eine andere Aktion ausführen oder einen Fehler erzwingen, wenn der falsche Inhaltstyp angezeigt wird.
1
Der Browser analysiert den JSON-Text nicht automatisch für Sie, ist also response.textimmer noch eine Zeichenfolge.
nnnnnn
1
Sie wollen mir also sagen, dass das Setzen dieses Headers keinen Unterschied macht? Was ist dann der Zweck seiner Existenz?
php_nub_qq
2
@php_nub_qq: Der Zweck besteht darin, Ihnen mitzuteilen, was der Server zurückgegeben hat, damit Ihre Anwendung entsprechend damit umgehen kann. Der Browser analysiert den JSON nicht für Sie, Ihre App muss dies tun. Dieser Header sagt Ihnen, dass es JSON ist (oder sein sollte).
Rocket Hazmat

Antworten:

136

Der Content-TypeHeader wird nur als Information für Ihre Anwendung verwendet. Dem Browser ist es egal, was es ist. Der Browser gibt Ihnen nur die Daten aus dem AJAX-Aufruf zurück. Wenn Sie es als JSON analysieren möchten, müssen Sie dies selbst tun.

Der Header ist vorhanden, damit Ihre App erkennen kann, welche Daten zurückgegeben wurden und wie sie damit umgehen sollen. Sie müssen sich den Header ansehen und ihn application/jsondann als JSON analysieren.

So funktioniert jQuery. Wenn Sie ihm nicht sagen, was er mit dem Ergebnis tun soll, erkennt er Content-Typemit, was damit zu tun ist.

Rakete Hazmat
quelle
12
Das stimmt nicht ganz. Wenn Sie den header('Content-Type: application/json');Download bis Content-Disposition: attachment; filename=myfile.jsondahin nicht verwenden und erzwingen, erhalten Sie eine myfile.json.html. Wenn Sie diesen JSON-Header verwenden, erhalten Sie myfile.json.
Remi Grumeau
4
@RemiGrumeau Was ist "nicht ganz wahr"? Das Herunterladen von Dateien mit dem Browser ist etwas völlig anderes. Der Browser erwartet wahrscheinlich standardmäßig HTML, daher geht er davon aus, dass alles, was er empfängt, HTML ist, sofern nicht anders angegeben. Beim Herunterladen wird es .htmlan die Datei angehängt , da dies standardmäßig der Fall ist .
Bzeaman
2
Ich kenne den vollständigen Kontext des Problems hier nicht - ABER Browser (und Javascript) kümmern sich manchmal um den Inhaltstyp. Dieser Header kann sich auf die Heuristiken auswirken, die ein Browser zum Anzeigen von Inhalten verwendet, und das Senden von XML und JSON mit einem Inhaltstyp von Text / HTML kann häufig zu subtilen Fehlern in den zugrunde liegenden XHR-Anforderungen (oder den Ebenen Ihres Frameworks darüber) führen
Alan Storm
7

Content-Type: application/jsonist nur der Inhaltsheader. Der Inhaltsheader ist nur eine Information über den Typ der zurückgegebenen Daten, z. B. :: JSON, Bild (PNG, JPG usw.), HTML.

Beachten Sie, dass JSON in JavaScript ein Array oder Objekt ist. Wenn Sie alle Daten anzeigen möchten, verwenden Sie console.log anstelle von alert:

alert(response.text); // Will alert "[object Object]" string
console.log(response.text); // Will log all data objects

Wenn Sie den ursprünglichen JSON-Inhalt als Zeichenfolge benachrichtigen möchten, fügen Sie einfache Anführungszeichen (') hinzu:

echo "'" . json_encode(array('text' => 'omrele')) . "'";
// alert(response.text) will alert {"text":"omrele"}

Verwenden Sie keine doppelten Anführungszeichen. JavaScript wird dadurch verwirrt, da JSON für jeden Wert und Schlüssel doppelte Anführungszeichen verwendet:

echo '<script>var returndata=';
echo '"' . json_encode(array('text' => 'omrele')) . '"';
echo ';</script>';

// It will return the wrong JavaScript code:
<script>var returndata="{"text":"omrele"}";</script>
Unter Amrul
quelle
Tun Sie dies niemals, da ein String in einfachen Anführungszeichen echo "'" . json_encode(array('text' => 'it\'s wrong')) . "'"; unterbrochen wird (und in vielen Sprachen häufig vorkommt): Diese fehlerhafte Ausgabe wird erzeugt : '{"text":"it's wrong"}'. Verwenden Sie stattdessen : json_encode(json_encode(array('text' => 'it\'s good'))). Das Ergebnis wird korrekt "{\"text\":\"it's wrong\"}"
angezeigt
1

Der folgende Code hilft mir, ein JSON-Objekt für JavaScript im Frontend zurückzugeben

Mein Vorlagencode

template_file.json

{
    "name": "{{name}}"
}

Von Python unterstützter Code

def download_json(request):
    print("Downloading JSON")
    # Response render a template as JSON object
    return HttpResponse(render_to_response("template_file.json",dict(name="Alex Vera")),content_type="application/json")    

Datei url.py.

url(r'^download_as_json/$', views.download_json, name='download_json-url')

jQuery-Code für das Frontend

  $.ajax({
        url:'{% url 'download_json-url' %}'        
    }).done(function(data){
        console.log('json ', data);
        console.log('Name', data.name);
        alert('hello ' + data.name);
    });
Alex Vera
quelle