1

I am having trouble sending a JavaScript objects over a http request. The http endpoing only accepts json content-type ("application/json" or "text/json")

I am not sure why data2 ( stringified json ) works fine But, data1 ( json object ) throws http 400 Bad Request. i.e why is jQuery not serializing the json object to a valid json string for the server to process.

var data1 = ({ rating : 3 });  //does not work
var data2 = '{ "rating" : 3}'; //works fine

$.ajax({
    url : "/rate",
    data : data1,
    type : "POST",
    contentType: "application/json",
    success: function(json){
        console.log("Ajax Return :"+json);
    }
});
smartnut007
  • 6,324
  • 6
  • 45
  • 52

5 Answers5

6

If you want to send a json string, you need to set processData equal to false, otherwise jQuery will process what is passed to data and convert it into a param string.

$.ajax({
    url: "/rate",
    data: data2,
    processData: false,
    contentType: "application/json",
    success: function(json) {
        console.log("Ajax Return :" + json);
    }
});​

Recently answered this here i guess: Setting the POST-body to a JSON object with jQuery

Community
  • 1
  • 1
Kevin B
  • 94,570
  • 16
  • 163
  • 180
  • I think you got it the other way round. Sending string works for me. But, sending the object dosent. – smartnut007 Jun 01 '12 at 21:42
  • If you want to send the object, you have to get rid of processData, however it will send them as either POST or GET params. I forget which is default. jQuery does not encode objects into json strings for you. – Kevin B Jun 01 '12 at 21:46
  • What error is happening? Also, please note that data1 is not a json object, it is a javascript object. data2 is a json string. – Kevin B Jun 01 '12 at 21:51
  • That sounds like a server-side error to me. What is the server expecting to receive? – Kevin B Jun 01 '12 at 21:54
  • The stackoverflow post you are referring to says you have to explicitly stringify the js object. Is this correct ? – smartnut007 Jun 01 '12 at 21:54
  • If the server is expecting a JSON string in the request body, yes. you need to convert your javascript object into a JSON string and use the `processData: false` option. – Kevin B Jun 01 '12 at 21:55
  • So, the server can be expecting something other than json string, when the content type is text/json or application/json ? – smartnut007 Jun 01 '12 at 22:03
2

By default data parameter values that is part of any ajax jQuery call, converts the JS object into a url-form-encoding i.e "param1=value&param2=value" string. This is the case for both GET and POST requests.

Interestingly, even if you explicitly specify { contentType : "application/json" } in the ajax method call, only the appropriate header is set, the JS object you pass as value for the data parameter is not converted to a JSON string ( one always hopes for more intelligence ), but still gets encoded as url-form-encoding. So, one has to explicitly convert the JS object to JSON string.

There are a options for doing so,

  1. JSON.stringify(obj); Its part of Javascript, I believe comes comes from ECMA 5 standard. Easiest, but the down side is it does not work in older browsers IE6 and before.
  2. jQuery json plugin that also has some additional features.
  3. Code from json.org

So, now my POST request that needs a json body would work like this.

var dataStr = JSON.stringify({ rating : 3 });  

$.ajax({
    url : "/rate",
    data : dataStr,
    type : "POST",
    contentType: "application/json",
    success: function(json){
        console.log("Ajax Return :"+json);
    }
});

Note: Effect of "processData" boolean parameter Some answer here mentioned that one has to set { processData : false }. But, this is not the case. This has an effect only when the type of "data" parameter is not a string. If its not a string then the default behavior is to convert the Object into url-form-encoding. But, this is mostly useless I think because if you pass a regular Object and processData is set to false, then it tries to do (data).toString which results in "[Object] [Object]" which is pretty useless.

smartnut007
  • 6,324
  • 6
  • 45
  • 52
  • Yup, this was the problem for me. I was sending a JSON object with the POST, but I wasn't stringifying it. Just read the beginning of your answer when it hit me :) Thanks! – Eduard Luca Aug 23 '13 at 08:09
1

Setting dataType to 'json' should work. Then you don't have to use JSON.stringify.

$.ajax({
    type: 'POST',
    url: '/rate',
    data: { rating : 3 },
    dataType: 'json',
    success: function (d) { ... }
}
Ivy
  • 887
  • 1
  • 7
  • 25
  • Thanks for pointing this out. Doing data: JSON.stringify(data) was causing my simple POST operation to take 8+ seconds to run. Much faster without it. – Hugh Seagraves Feb 12 '19 at 20:14
0

data1 is an object, data2 is a string. They will be sent to the server as such.

robbymurphy
  • 741
  • 2
  • 5
  • 16
0

I realize this is an old post but here is the solution that worked for me. Setting the dataType as 'json' and removing the contentType altogether should do the trick. Here's the full code:

var data1 = { rating : 3 };

    $.ajax({
        url : "/rate",
        data : data1,
        dataType: 'json',
        type : "POST",
        //contentType: "application/json",
        success: function(json){
            console.log("Ajax Return :"+json);
        }
    });
beastieboy
  • 833
  • 8
  • 15