155
votes

I have always been trying to avoid using most of the HTTP protocol's properties for the sake of fear of the unknown.

However, I said to myself that I'm going to face fear today and start using headers purposefully. I have been trying to send json data to the browser and use it right away. For example, if I have an Ajax handler function on ready state 4 which looks like so:

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

And I have set the content-type header in my PHP code:

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

Why can't I directly access the property from the handler function, when the browser is clearly told that the incoming data is application/json?

4
If i understand correctly, you would like to use text as a javascript variable in the handler and not response? That would be very weird functionality. The json_encode also creates 1 object out of your PHP array. So when you get this into javascript it needs to be assigned to a variable.Flashin
The contentType header is information only. The browser will use that if it can, but in this case the browsers simply ignore it because they don't usually know what the intent is. Your Javascript application can make use of it. You're assuming that JSON will be presented, so you can decode it with JSON.parse(). You could take some different action, or force an error if the wrong contentType appears.user1864610
The browser doesn't automatically parse the JSON text for you, so response.text is still a string.nnnnnn
So you mean to tell me that setting that header makes no difference what so ever? What is the purpose of it's existence then?php_nub_qq
@php_nub_qq: It's purpose is to tell you what the server returned so your application can handle it accordingly. The browser won't parse the JSON for you, your app needs to do that. This header is telling you that it is (or should be JSON).Rocket Hazmat

4 Answers

144
votes

The Content-Type header is just used as info for your application. The browser doesn't care what it is. The browser just returns you the data from the AJAX call. If you want to parse it as JSON, you need to do that on your own.

The header is there so your app can detect what data was returned and how it should handle it. You need to look at the header, and if it's application/json then parse it as JSON.

This is actually how jQuery works. If you don't tell it what to do with the result, it uses the Content-Type to detect what to do with it.

10
votes

Content-Type: application/json is just the content header. The content header is just information about the type of returned data, ex::JSON,image(png,jpg,etc..),html.

Keep in mind, that JSON in JavaScript is an array or object. If you want to see all the data, use console.log instead of alert:

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

If you want to alert the original JSON content as a string, then add single quotation marks ('):

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

Do not use double quotes. It will confuse JavaScript, because JSON uses double quotes on each value and key:

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>
1
votes

The below code helps me to return a JSON object for JavaScript on the front end

My template code

template_file.json

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

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

File url.py

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

jQuery code for the front end

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

Recently ran into a problem with this and a Chrome extension that was corrupting a JSON stream when the response header labeled the content-type as 'text/html' apparently extensions can and will use the response header to alter the content prior to further processing by the browser. Changing the content-type fixed the issue.