Intestazione del tipo di contenuto HTTP e JSON


144

Ho sempre cercato di evitare di usare la maggior parte delle proprietà del protocollo HTTP per paura dell'ignoto.

Tuttavia, mi sono detto che oggi affronterò la paura e inizierò a usare le intestazioni intenzionalmente. Ho cercato di inviare jsondati al browser e di utilizzarli immediatamente. Ad esempio, se ho una funzione di gestore Ajax nello stato pronto 4 che assomiglia a questo:

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

E ho impostato l'intestazione del tipo di contenuto nel mio codice PHP:

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

Perché non riesco ad accedere direttamente alla proprietà dalla funzione del gestore, quando al browser viene comunicato chiaramente che i dati in arrivo sono application/json?


Se ho capito bene, vorresti usare textcome variabile javascript nel gestore e non una risposta? Sarebbe una funzionalità molto strana. Json_encode crea anche 1 oggetto dal tuo array PHP. Quindi quando lo ottieni in JavaScript deve essere assegnato a una variabile.
Flashin

4
L'intestazione contentType è solo a scopo informativo. Il browser lo userà se possibile, ma in questo caso i browser semplicemente lo ignorano perché di solito non sanno quale sia l'intento. La tua applicazione Javascript può farne uso. Stai assumendo che JSON verrà presentato, quindi puoi decodificarlo con JSON.parse(). È possibile eseguire alcune azioni diverse o forzare un errore se viene visualizzato ContentType errato.

1
Il browser non analizza automaticamente il testo JSON per te, quindi response.textè ancora una stringa.
nnnnnn,

1
Quindi vuoi dire che l'impostazione di quell'intestazione non fa differenza che mai? Qual è lo scopo della sua esistenza allora?
php_nub_qq

2
@php_nub_qq: lo scopo è quello di dirti ciò che il server ha restituito in modo che l'applicazione possa gestirlo di conseguenza. Il browser non analizzerà JSON per te, la tua app deve farlo. Questa intestazione ti dice che è (o dovrebbe essere JSON).
Rocket Hazmat,

Risposte:


136

L' Content-Typeintestazione viene utilizzata solo come informazioni per l'applicazione. Al browser non importa cosa sia. Il browser ti restituisce semplicemente i dati della chiamata AJAX. Se vuoi analizzarlo come JSON, devi farlo da solo.

L'intestazione è lì in modo che la tua app possa rilevare quali dati sono stati restituiti e come dovrebbero gestirli. Devi guardare l'intestazione e se è application/jsonquindi analizzarla come JSON.

Ecco come funziona jQuery. Se non gli dici cosa fare con il risultato, lo usa Content-Typeper rilevare cosa farne.


12
Questo non è del tutto vero. Se non usi header('Content-Type: application/json');e imponi il download entro Content-Disposition: attachment; filename=myfile.json, finirai con un myfile.json.html. Usando questa intestazione json, otterrai myfile.json.
Remi Grumeau,

4
@RemiGrumeau Che cos'è 'non del tutto vero'? Il download di file con il browser è qualcosa di completamente diverso. Il browser probabilmente si aspetterà di default l'HTML, quindi presuppone che tutto ciò che riceve sia HTML se non diversamente specificato. Durante il download, si aggiunge .htmlal file, perché è quello che è predefinito.
bzeaman,

2
Non conosco il contesto completo del problema qui - MA a volte i browser (e javascript) si preoccupano di Content-Type. Questa intestazione può influire sull'euristica utilizzata da un browser per visualizzare il contenuto e l'invio di XML e JSON con un tipo di contenuto di testo / html può spesso creare bug sottili nelle richieste XHR sottostanti (o livelli del framework in cima a quelli)
Alan Storm

7

Content-Type: application/jsonè solo l'intestazione del contenuto. L'intestazione del contenuto è solo informazioni sul tipo di dati restituiti, ad es .: JSON, immagine (png, jpg, ecc.), HTML.

Tieni presente che JSON in JavaScript è un array o un oggetto. Se vuoi vedere tutti i dati, usa console.log invece di alert:

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

Se si desidera avvisare il contenuto JSON originale come stringa, quindi aggiungere le virgolette singole ('):

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

Non usare virgolette doppie. Confonderà JavaScript, perché JSON utilizza virgolette doppie su ciascun valore e chiave:

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>

Mai fare questo, si romperà in qualsiasi stringa utilizzando le virgolette singole (ed è frequente in molte lingue): echo "'" . json_encode(array('text' => 'it\'s wrong')) . "'"; produrrà questo output rotto: '{"text":"it's wrong"}'. Utilizzare questo, invece: json_encode(json_encode(array('text' => 'it\'s good'))). Il risultato sarà "{\"text\":\"it's wrong\"}"
salvato

1

Il codice seguente mi aiuta a restituire un oggetto JSON per JavaScript sul front-end

Il mio codice modello

template_file.json

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

Codice supportato da Python

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")    

File url.py

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

codice jQuery per il front-end

  $.ajax({
        url:'{% url 'download_json-url' %}'        
    }).done(function(data){
        console.log('json ', data);
        console.log('Name', data.name);
        alert('hello ' + data.name);
    });
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.