En-tête de type de contenu HTTP et JSON


144

J'ai toujours essayé d'éviter d'utiliser la plupart des propriétés du protocole HTTP par peur de l'inconnu.

Cependant, je me suis dit que je vais affronter la peur aujourd'hui et commencer à utiliser les en-têtes à dessein. J'ai essayé d'envoyer des jsondonnées au navigateur et de les utiliser immédiatement. Par exemple, si j'ai une fonction de gestionnaire Ajax sur l'état prêt 4 qui ressemble à ceci:

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

Et j'ai défini l'en-tête de type de contenu dans mon code PHP:

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

Pourquoi ne puis-je pas accéder directement à la propriété à partir de la fonction de gestionnaire, alors que le navigateur est clairement informé que les données entrantes sont application/json?


Si je comprends bien, vous souhaitez utiliser textcomme variable javascript dans le gestionnaire et non comme réponse? Ce serait une fonctionnalité très étrange. Le json_encode crée également 1 objet à partir de votre tableau PHP. Donc, lorsque vous obtenez cela en javascript, il doit être affecté à une variable.
Flashin

4
L'en-tête contentType est fourni uniquement à titre d'information. Le navigateur l'utilisera s'il le peut, mais dans ce cas, les navigateurs l'ignorent simplement car ils ne savent généralement pas quelle est l'intention. Votre application Javascript peut en faire usage. Vous supposez que JSON sera présenté, vous pouvez donc le décoder avec JSON.parse(). Vous pouvez effectuer une action différente ou forcer une erreur si le type de contenu incorrect apparaît.

1
Le navigateur n'analyse pas automatiquement le texte JSON pour vous, c'est donc response.texttoujours une chaîne.
nnnnnn

1
Vous voulez donc me dire que définir cet en-tête ne fait aucune différence quoi que ce soit? Quel est le but de son existence alors?
php_nub_qq

2
@php_nub_qq: Son but est de vous dire ce que le serveur a renvoyé afin que votre application puisse le gérer en conséquence. Le navigateur n'analysera pas le JSON pour vous, votre application doit le faire. Cet en-tête vous indique que c'est (ou devrait être JSON).
Rocket Hazmat

Réponses:


136

L'en- Content-Typetête est simplement utilisé comme information pour votre application. Le navigateur ne se soucie pas de ce que c'est. Le navigateur vous renvoie simplement les données de l'appel AJAX. Si vous souhaitez l'analyser en tant que JSON, vous devez le faire vous-même.

L'en-tête est là pour que votre application puisse détecter quelles données ont été renvoyées et comment elle doit les gérer. Vous devez regarder l'en-tête, et si c'est application/jsonalors l'analyser comme JSON.

C'est en fait ainsi que fonctionne jQuery. Si vous ne lui dites pas quoi faire avec le résultat, il utilise Content-Typepour détecter ce qu'il faut en faire.


12
Ce n'est pas totalement vrai. Si vous n'utilisez pas header('Content-Type: application/json');et ne forcez pas le téléchargement d'ici Content-Disposition: attachment; filename=myfile.jsonlà, vous vous retrouverez avec un fichier myfile.json.html. En utilisant cet en-tête json, vous obtiendrez myfile.json.
Remi Grumeau

4
@RemiGrumeau Qu'est-ce qui n'est pas totalement vrai? Le téléchargement de fichiers avec un navigateur est quelque chose de complètement différent. Le navigateur attendra probablement par défaut du HTML, donc il suppose que tout ce qu'il reçoit est du HTML, sauf indication contraire. Lors du téléchargement, il s'ajoute .htmlau fichier, car c'est ce dont il est par défaut.
bzeaman

2
Je ne connais pas le contexte complet du problème ici - MAIS, les navigateurs (et javascript) se soucient parfois de Content-Type. Cet en-tête peut avoir un impact sur l'heuristique qu'un navigateur utilise pour afficher le contenu, et l'envoi de XML et de JSON avec un type de contenu texte / html peut souvent créer des bogues subtils dans les requêtes XHR sous-jacentes (ou les couches de votre framework en plus de celles-ci)
Alan Storm

7

Content-Type: application/jsonest juste l'en-tête du contenu. L'en-tête de contenu est juste une information sur le type de données renvoyées, ex :: JSON, image (png, jpg, etc.), html.

Gardez à l'esprit que JSON en JavaScript est un tableau ou un objet. Si vous voulez voir toutes les données, utilisez console.log au lieu d'alerte:

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

Si vous souhaitez alerter le contenu JSON d'origine sous forme de chaîne, ajoutez des guillemets simples ('):

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

N'utilisez pas de guillemets doubles. Cela confondra JavaScript, car JSON utilise des guillemets doubles sur chaque valeur et clé:

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>

Jamais cela, il se brisera sur une chaîne en utilisant des guillemets simples (et il est fréquent dans de nombreuses langues): echo "'" . json_encode(array('text' => 'it\'s wrong')) . "'"; produira cette sortie brisée: '{"text":"it's wrong"}'. Utilisez ceci: json_encode(json_encode(array('text' => 'it\'s good'))). Le résultat sera correctement échappé:"{\"text\":\"it's wrong\"}"
PofMagicfingers

1

Le code ci-dessous m'aide à renvoyer un objet JSON pour JavaScript sur le front-end

Mon code de modèle

template_file.json

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

Code soutenu par 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")    

Fichier url.py

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

code jQuery pour le frontal

  $.ajax({
        url:'{% url 'download_json-url' %}'        
    }).done(function(data){
        console.log('json ', data);
        console.log('Name', data.name);
        alert('hello ' + data.name);
    });
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.