Заголовок HTTP Content-Type и JSON

147

Я всегда старался избегать использования большинства свойств протокола HTTP из страха перед неизвестным.

Однако я сказал себе, что сегодня столкнусь со страхом и начну целенаправленно использовать заголовки. Я пытаюсь отправить jsonданные в браузер и сразу же ими воспользоваться. Например, если у меня есть функция обработчика Ajax в состоянии готовности 4, которая выглядит так:

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

И я установил заголовок типа содержимого в своем PHP-коде:

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

Почему я не могу напрямую получить доступ к свойству из функции-обработчика, когда браузеру четко сказано, что входящие данные есть application/json?

php_nub_qq
источник
Если я правильно понимаю, вы хотели бы использовать textв обработчике переменную javascript, а не ответ? Это было бы очень странно. Json_encode также создает 1 объект из вашего массива PHP. Поэтому, когда вы добавляете это в javascript, его необходимо присвоить переменной.
Flashin
4
Заголовок contentType предназначен только для информации. Браузер будет использовать это, если может, но в этом случае браузеры просто игнорируют это, потому что они обычно не знают, каково намерение. Ваше приложение Javascript может использовать это. Вы предполагаете, что будет представлен JSON, поэтому вы можете его декодировать с помощью JSON.parse(). Вы можете предпринять другие действия или вызвать ошибку, если отображается неправильный тип содержимого.
1
Браузер не анализирует текст JSON автоматически, поэтому response.textон все еще является строкой.
nnnnnn
1
Итак, вы хотите сказать мне, что установка этого заголовка не имеет никакого значения? В чем тогда цель его существования?
php_nub_qq
2
@php_nub_qq: его цель - сообщить вам, что вернул сервер, чтобы ваше приложение могло обработать это соответствующим образом. Браузер не разобрать JSON для вас, ваше приложение должно сделать это. Этот заголовок сообщает вам, что это (или должен быть JSON).
Rocket Hazmat

Ответы:

137

Content-TypeЗаголовок используются только в качестве информации для вашего приложения. Браузеру все равно, что это такое. Браузер просто возвращает вам данные из вызова AJAX. Если вы хотите разобрать его как JSON, вам нужно сделать это самостоятельно.

Заголовок присутствует, поэтому ваше приложение может определить, какие данные были возвращены и как оно должно их обрабатывать. Вам нужно посмотреть заголовок и, если он, application/jsonпроанализировать его как JSON.

Именно так работает jQuery. Если вы не укажете ему, что делать с результатом, он Content-Typeбудет определять, что с ним делать.

Ракетный Хазмат
источник
13
Это не совсем так. Если вы не используете header('Content-Type: application/json');и не загрузите принудительно к тому Content-Disposition: attachment; filename=myfile.jsonвремени, вы получите файл myfile.json.html. Используя этот заголовок json, вы получите myfile.json.
Реми Грумо, 04
4
@RemiGrumeau Что значит «не совсем правда»? Скачивание файлов через браузер - это совсем другое дело. Браузер, вероятно, по умолчанию ожидает HTML, поэтому он предполагает, что все, что он получает, является HTML, если не указано иное. При загрузке он добавляется .htmlв файл, потому что это то, что по умолчанию.
bzeaman
2
Я не знаю полного контекста проблемы здесь - НО, браузеры (и javascript) иногда заботятся о Content-Type. Этот заголовок может повлиять на эвристику, которую браузер использует для отображения контента, а отправка XML и JSON с типом контента text / html часто может создавать небольшие ошибки в базовых запросах XHR (или в слоях вашего фреймворка поверх них)
Алан Сторм
8

Content-Type: application/jsonэто просто заголовок содержимого. Заголовок содержимого - это просто информация о типе возвращаемых данных, например: JSON, изображение (png, jpg и т. Д.), Html.

Имейте в виду, что JSON в JavaScript - это массив или объект. Если вы хотите увидеть все данные, используйте console.log вместо alert:

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

Если вы хотите предупредить исходное содержимое JSON в виде строки, добавьте одинарные кавычки ('):

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

Не используйте двойные кавычки. Это запутает JavaScript, потому что JSON использует двойные кавычки для каждого значения и ключа:

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>
Среди Амрула
источник
Никогда не делайте этого, он сломается на любой строке , используя одиночные кавычки (и это часто в разных языках): echo "'" . json_encode(array('text' => 'it\'s wrong')) . "'"; будет производить этот сломанный вывод: '{"text":"it's wrong"}'. Используйте вместо этого: json_encode(json_encode(array('text' => 'it\'s good'))). Результат будет экранирован правильно:"{\"text\":\"it's wrong\"}"
PofMagicfingers
1

Приведенный ниже код помогает мне вернуть объект JSON для JavaScript во внешнем интерфейсе.

Мой код шаблона

template_file.json

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

Код, поддерживаемый 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")    

Файл url.py

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

код jQuery для внешнего интерфейса

  $.ajax({
        url:'{% url 'download_json-url' %}'        
    }).done(function(data){
        console.log('json ', data);
        console.log('Name', data.name);
        alert('hello ' + data.name);
    });
Алекс Вера
источник
0

Недавно возникла проблема с этим и с расширением Chrome, которое искажало поток JSON, когда заголовок ответа помечал тип содержимого как «текст / html», по-видимому, расширения могут и будут использовать заголовок ответа для изменения содержимого до дальнейшей обработки с помощью браузер. Изменение типа содержимого устранило проблему.

LANimation Big Bad Apps
источник