196

Can someone explain in an easy way how to make jQuery send actual JSON instead of a query string?

$.ajax({
    url      : url,
    dataType : 'json', // I was pretty sure this would do the trick
    data     : data,
    type     : 'POST',
    complete : callback // etc
});

This will in fact convert your carefully prepared JSON to a query string. One of the annoying things is that any array: [] in your object will be converted to array[]: [], probably because of limitations of the query sting.

Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
Redsandro
  • 11,060
  • 13
  • 76
  • 106
  • 7
    The `dataType` has no bearing on how the data is sent. It merely specifies what the type of data is you expect to have **returned** by the call. If you want to indicate to the server what the type of data is you are specifying in the `data` property you need to set the `contentType` property similar to `contentType: "application/json"` – Nope Oct 02 '12 at 16:05
  • Thanks for clarifying. But in that case, why do I need to specify the response type client-side if the server is providing a content-type header in the response? – Redsandro Oct 02 '12 at 20:20
  • 2
    You don't *have* to specify it, by default jQuery will try and make an intelligent guess based on the MIME type of the response. However, by specifying it you are telling jQuery explicitly what type you are expecting from the server and jQuery will attempt to convert the response to an object of that type. Not specifying it and leaving jQuery take a guess may result in jQuery converting the response into an unexpected format, even though you sent JSON from the server. Check the documentation for more details on the dataType: http://api.jquery.com/jQuery.ajax/ – Nope Oct 02 '12 at 22:08
  • Possible duplicate of [Jquery Ajax Posting json to webservice](http://stackoverflow.com/questions/6323338/jquery-ajax-posting-json-to-webservice) – Madura Pradeep Apr 21 '16 at 17:30

4 Answers4

283

You need to use JSON.stringify to first serialize your object to JSON, and then specify the contentType so your server understands it's JSON. This should do the trick:

$.ajax({
    url: url,
    type: "POST",
    data: JSON.stringify(data),
    contentType: "application/json",
    complete: callback
});

Note that the JSON object is natively available in browsers that support JavaScript 1.7 / ECMAScript 5 or later. If you need legacy support you can use json2.

Mark Amery
  • 143,130
  • 81
  • 406
  • 459
mekwall
  • 28,614
  • 6
  • 75
  • 77
  • 14
    This will not work, you're missing `contentType: 'application/json'`. – Ohgodwhy Oct 02 '12 at 16:04
  • @Ohgodwhy Oh yeah. That went a bit too fast ;) – mekwall Oct 02 '12 at 16:05
  • 1
    Thanks. I thought dataType took care of this, but I got that backwards. Any thoughts on specifying charset in the content-type like Bergi did in the other answer? – Redsandro Oct 02 '12 at 20:17
  • 5
    @Redsandro That shouldn't be necessary. According to jQuery docs: `POST data will always be transmitted to the server using UTF-8 charset, per the W3C XMLHTTPRequest standard` – mekwall Oct 03 '12 at 10:47
  • on server side when i do `print_r` on `$_POST ` array is empty, but ajax request shows it has posted 7 json items – shorif2000 Apr 01 '15 at 09:54
  • @Xufox I undid your edit to the answer because I thought it was liable to cause confusion; the edit *presumes* without saying so that the request is cross-domain, but there's no indication of that in the question. I'll leave your next step up to you; I suggest just letting things be, but you could also apply a tweaked version of the edit that explains *when* it applies, or post an answer of your own, or, if you think the edit was fine as it was, just straight up rollback my rollback (in which case we can go and fight on Meta). Either way, feel free to flag this comment as NLN when you see it. – Mark Amery Nov 18 '18 at 15:20
  • 1
    @shorif2000 better late than never... the problem is that in `$_POST` in php you can only see `application/x-www-form-urlencoded`, if you want to read json data you must do `file_get_contents("php://input")` and perhaps then a `json_decode()` – santiago arizti Nov 23 '18 at 15:33
31

No, the dataType option is for parsing the received data.

To post JSON, you will need to stringify it yourself via JSON.stringify and set the processData option to false.

$.ajax({
    url: url,
    type: "POST",
    data: JSON.stringify(data),
    processData: false,
    contentType: "application/json; charset=UTF-8",
    complete: callback
});

Note that not all browsers support the JSON object, and although jQuery has .parseJSON, it has no stringifier included; you'll need another polyfill library.

raffian
  • 31,267
  • 26
  • 103
  • 174
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • 4
    Setting `processData` to `false` isn't necessary since `JSON.stringify` already returns a string. – mekwall Oct 02 '12 at 16:10
  • @MarcusEkwall: Afaik it still would be `encodeURIComponent`ed, wouldn't it? – Bergi Oct 02 '12 at 16:11
  • OK, it might not be needed, but do you really think it would make the request fail? – Bergi Oct 02 '12 at 16:18
  • It shouldn't make it fail, considering it's a string already. – Kevin B Oct 02 '12 at 17:47
  • It won't fire since JSON is no longer a URI component, but it won't hurt either. Thanks for the answer. I upvoted both, but accepted the highest scoring answer. – Redsandro Oct 02 '12 at 20:23
  • Anyway, coinciding with the source of my confusion in the first place, any idea why I would need to specify the response type `client-side` if the `server` is providing a `content-type` header in the response either way? It's like me saying to you: _"I'm gonna tell you three numbers!"_ and somebody else whispers in your ear: _"He's gonna tell you three numbers."_ Kinda duh. – Redsandro Oct 02 '12 at 20:26
  • Just too late to edit my previous comment, but I see as long as the header is sent, I do not have to specify it. _If none is specified, jQuery will try to infer it based on the MIME type of the response (an XML MIME type will yield XML, in 1.4 JSON will yield a JavaScript object, in 1.4 script will execute the script, and anything else will be returned as a string)._ I guess some people like their I/O very strict, and have jQuery only listen to a certain content-type. – Redsandro Oct 02 '12 at 20:35
  • 1
    @Redsandro: Yeah, it's doing an "intelligent guess". However, the reason for the parameter is not (only) that people want to make it strict, but more that they don't set appropriate MIME types in their server responses. – Bergi Oct 02 '12 at 21:43
  • Setting `processData: false` + using JSON.stringify was the important part for me using JQuery 1.9. – Keith Oct 23 '15 at 14:36
5

While I know many architectures like ASP.NET MVC have built-in functionality to handle JSON.stringify as the contentType my situation is a little different so maybe this may help someone in the future. I know it would have saved me hours!

Since my http requests are being handled by a CGI API from IBM (AS400 environment) on a different subdomain these requests are cross origin, hence the jsonp. I actually send my ajax via javascript object(s). Here is an example of my ajax POST:

 var data = {USER : localProfile,  
        INSTANCE : "HTHACKNEY",  
        PAGE : $('select[name="PAGE"]').val(), 
        TITLE : $("input[name='TITLE']").val(), 
        HTML : html,
        STARTDATE : $("input[name='STARTDATE']").val(), 
        ENDDATE : $("input[name='ENDDATE']").val(),
        ARCHIVE : $("input[name='ARCHIVE']").val(), 
        ACTIVE : $("input[name='ACTIVE']").val(), 
        URGENT : $("input[name='URGENT']").val(), 
        AUTHLST :  authStr};
        //console.log(data);
       $.ajax({
            type: "POST",
           url:   "http://www.domian.com/webservicepgm?callback=?",
           data:  data,
           dataType:'jsonp'
       }).
       done(function(data){
         //handle data.WHATEVER
       });
yardpenalty.com
  • 1,244
  • 2
  • 17
  • 32
  • 2
    Thanks for adding more knowledge to this question! The satisfying answer had already been given, but I upvoted yours. – Redsandro Sep 04 '16 at 11:24
1

If you are sending this back to asp.net and need the data in request.form[] then you'll need to set the content type to "application/x-www-form-urlencoded; charset=utf-8"

Original post here

Secondly get rid of the Datatype, if your not expecting a return the POST will wait for about 4 minutes before failing. See here

Community
  • 1
  • 1
Tod
  • 2,070
  • 21
  • 27