Cabeçalho do tipo de conteúdo HTTP e JSON

144

Eu sempre tentei evitar o uso da maioria das propriedades do protocolo HTTP por medo do desconhecido.

No entanto, eu disse a mim mesmo que hoje vou enfrentar o medo e começar a usar os cabeçalhos de propósito. Eu tenho tentado enviar jsondados para o navegador e usá-los imediatamente. Por exemplo, se eu tiver uma função de manipulador Ajax no estado pronto 4, com a seguinte aparência:

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

E eu configurei o cabeçalho do tipo de conteúdo no meu código PHP:

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

Por que não consigo acessar diretamente a propriedade a partir da função manipuladora, quando o navegador é informado claramente de que os dados são recebidos application/json?

php_nub_qq
fonte
Se eu entendi corretamente, você gostaria de usar textcomo uma variável javascript no manipulador e não como resposta? Isso seria uma funcionalidade muito estranha. O json_encode também cria 1 objeto da sua matriz PHP. Portanto, quando você coloca isso em javascript, ele precisa ser atribuído a uma variável.
Flashin
4
O cabeçalho contentType é apenas informativo. O navegador usará isso se puder, mas nesse caso os navegadores simplesmente o ignoram porque geralmente não sabem qual é a intenção. Seu aplicativo Javascript pode fazer uso dele. Você está assumindo que o JSON será apresentado, para que você possa decodificá-lo JSON.parse(). Você pode executar alguma ação diferente ou forçar um erro se o contentType errado aparecer.
1
O navegador não analisa automaticamente o texto JSON para você, portanto response.textainda é uma sequência.
Nnnnnn
1
Então você quer me dizer que definir esse cabeçalho não faz diferença? Qual é o propósito de sua existência então?
Php_nub_qq
2
@php_nub_qq: Seu objetivo é informar o que o servidor retornou para que seu aplicativo possa lidar com isso de acordo. O navegador não analisa o JSON para você, seu aplicativo precisa fazer isso. Este cabeçalho está lhe dizendo que é (ou deveria ser JSON).
Rocket Hazmat

Respostas:

136

O Content-Typecabeçalho é usado apenas como informação para o seu aplicativo. O navegador não se importa com o que é. O navegador apenas retorna os dados da chamada AJAX. Se você quiser analisá-lo como JSON, precisará fazer isso por conta própria.

O cabeçalho está lá para que seu aplicativo possa detectar quais dados foram retornados e como eles devem ser tratados. Você precisa olhar para o cabeçalho e, se for, application/jsonanalisá-lo como JSON.

É assim que o jQuery funciona. Se você não informar o que fazer com o resultado, ele será usado Content-Typepara detectar o que fazer com o resultado.

Foguete Hazmat
fonte
12
Isso não é totalmente verdade. Se você não usar header('Content-Type: application/json');e forçar o download até Content-Disposition: attachment; filename=myfile.jsonentão, você terminará com a myfile.json.html. Usando este cabeçalho json, você receberá myfile.json.
Remi Grumeau
4
@RemiGrumeau O que é 'não é totalmente verdade'? Baixar arquivos com o navegador é algo completamente diferente. O navegador provavelmente usará o HTML como padrão, portanto assume que tudo o que recebe é HTML, a menos que especificado de outra forma. Ao fazer o download, ele anexa .htmlao arquivo, porque é o que ele usa como padrão.
precisa saber é o seguinte
2
Não conheço o contexto completo do problema aqui - MAS, às vezes, navegadores (e javascript) se preocupam com o Tipo de conteúdo. Esse cabeçalho pode afetar as heurísticas que um navegador usa para exibir conteúdo, e o envio de XML e JSON com um tipo de conteúdo de texto / html geralmente pode criar bugs sutis nas solicitações XHR subjacentes (ou nas camadas da sua estrutura em cima delas)
Alan Storm
7

Content-Type: application/jsoné apenas o cabeçalho do conteúdo. O cabeçalho do conteúdo é apenas informações sobre o tipo de dados retornados, ex: JSON, imagem (png, jpg, etc.), html.

Lembre-se de que JSON em JavaScript é uma matriz ou objeto. Se você deseja ver todos os dados, use console.log em vez de alerta:

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

Se você deseja alertar o conteúdo JSON original como uma sequência, adicione aspas simples ('):

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

Não use aspas duplas. Isso confundirá o JavaScript, porque o JSON usa aspas duplas em cada valor e chave:

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>
Entre Amrul
fonte
Nunca faça isso, ele vai quebrar em qualquer string usando aspas simples (e é frequente em muitas línguas): echo "'" . json_encode(array('text' => 'it\'s wrong')) . "'"; irá produzir esta saída quebrado: '{"text":"it's wrong"}'. Utilize este em vez disso: json_encode(json_encode(array('text' => 'it\'s good'))). O resultado será escapado corretamente:"{\"text\":\"it's wrong\"}"
PofMagicfingers 11/11/19
1

O código abaixo me ajuda a retornar um objeto JSON para JavaScript no front-end

O código do meu modelo

template_file.json

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

Código suportado por 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")    

Arquivo url.py

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

Código jQuery para o front end

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