Sending JavaScript Object through AJAX works, JSON doesn't? - javascript

I'm trying to send data through AJAX and most places I read online say I need to send it as JSON. However, If I try to send it as JavaScript Object it actually works, wheres if I try to send it as JSON it gives me a CORS error (but that's another topic: here's a link to the issue: API Gateway CORS: no 'Access-Control-Allow-Origin' header (NON-PROXY)).
I guess my question is, is it perfectly fine for me to send the data as JavaScript object as oppose to JSON? is there a benefit of doing one over the other?
Example:
This works: (Sending data as JS Object):
$("#xform").submit(function (event) {
event.preventDefault();
var obj = { xnumber: 1 };
$.ajax({
type: 'GET',
url: 'adddresshere',
data: obj,
dataType: 'json',
contentType: 'application/json',
}).done(function (result) {
table.clear();
table.rows.add(result).draw();
});
});
This doesn't work - (sending data as JSON)
$("#xform").submit(function (event) {
event.preventDefault();
var obj = { xnumber: 1 };
var myJSON = JSON.stringify(obj);
$.ajax({
type: 'GET',
url: 'adddresshere',
data: myJSON,
dataType: 'json',
contentType: 'application/json',
}).done(function (result) {
table.clear();
table.rows.add(result).draw();
});
});
So can I just stick with sending JS object from now on as long as it works (like it does for me right now)?

Short Answer is Yes.
Explanation:
When the online blogs says that you need to pass JSON objects - They mean you need to send Java Script Object Notation objects. When you write it like:
var obj = { xnumber: 1 }
You are already creating a JSON object. This is good to send via ajax call. When you do a JSON stringify operation, it basically converts the above JSON into string. Hence, the server is unable to treat as JSON object and it will fail.

Your JavaScript Object is deserialized JSON. As Heretic Monkey pointed out, JSON.stringify serializes your JavaScript Object to be sent over the wire.

Related

Strange behavior when sending JSON over AJAX

I am encountering some really strange behavior when sending JSON over AJAX.
JSON data:
data = {
"name": "box1",
"comment": ["fragile"],
"type_A": [
{
"item": "1",
"attr": [
"big",
"red"
]
},
{
"item": "2",
"attr": [
"small",
"red"
]
},
],
"type_B": [],
"misc": {}
};
POST request:
$.ajax({
url: url,
type: "POST",
// data: JSON.stringify(data),
data: data,
success: function (result) {
console.log("inside success");
},
error: function (error) {
console.log("inside error");
}
});
If I pass in data here without JSON.stringify(), the empty fields type_B and misc get lost/stripped away. But if I do use JSON.stringify() then the backend cannot parse it properly without JSON.parse(). Is there a way to not strip away empty fields without doing a JSON.parse() in the backend?
I tried adding contentType: "application/json" and dataType: "json" to the request but didn't help.
What you have labeled "JSON data" is not JSON. It is a JavaScript object literal. It is part of JavaScript source code. It is not a JSON data file.
When you use jQuery's Ajax functions you can pass a few different things to data.
If you pass it an object, then jQuery will Form URL Encode it.
URL Encoded data has no standard way to represent anything other than a set of flat key=value pairs.
PHP introduced an extension which lets you express arrays and associative arrays by using square brackets in the key names. For example:
array[]=item1&array[]=item2
Each items in the array is represented by a copy of the key.
If you have no items, then there are no keys of that name.
If you use this method of encoding data then you cannot express empty arrays. The closest you could come would be to have an array containing a zero length string.
If you pass it a string, then jQuery will just send it as is.
Using JSON.stringify will convert your object to a string containing JSON data.
JSON is capable of expressing empty arrays.
PHP, however, will not automatically parse JSON formatted requests.
So…
Is there a way to not strip away empty fields without doing a JSON.parse() in the backend?
No. There isn't. You either use a format which doesn't support empty fields, or you use a format which PHP won't automatically parse for you.
I tried adding contentType: "application/json"
This tells the server that the data you are sending is encoded as JSON. If you are sending JSON then you should include this.
It doesn't alter the data you send. You need to encode the data as JSON yourself.
and dataType: "json" to the request but didn't help.
This tells the server that you expect the response to the request to contain JSON. It also tells jQuery to ignore the content-type of the response and parse it as JSON whatever the server says it is.
It has no effect on the data you send.
Jquery processes your data before sending and uses the request's post formdata instead of putting JSON in the body of the request.
To avoid this, use processData: false and contentType: 'application/json':
$.ajax({
url: url,
type: "POST",
processData: false,
contentType: 'application/json',
data: JSON.stringify(data),
success: function (result) {
console.log("inside success");
},
error: function (error) {
console.log("inside error");
}
});

Trying to understand JQuery/Ajax Get/POST calls

Correct me if I'm wrong but it was my understanding that a POST was to be used if I was changing data, and a GET was to be used if I want to retrieve data.
Based on that assumption.
I have (MVC5) app.
My JavaScript
function MyLoadData(myValue) {
$.ajax({
method: 'POST',
url: '/Home/GetMyData',
contentType: 'application/json',
dataType: 'json',
data: JSON.stringify({ "MyValue": myValue}),
success: function (data) {
// Do Stuff
}
});
and my controller.
public JsonResult GetMyData(string myValue)
{ // Do Stuff }
This only works if I set the method: 'POST', if I set it to 'GET' it will still make the server call but not pass the myValue to the controller.
Also of note there is no data annotation on the GetMyData method.
In this scenario shouldn't I be using GET to get my data from the controller?
UPDATED based on comments:
function MyLoadData(myValue) {
$.ajax({
method: 'POST',
url: '/Home/GetMyData',
dataType: 'json',
data: { "MyValue": myValue},
success: function (data) {
// Do Stuff
}
});
Both POST and GET methods can pass the myValue to the controller.
GET - Requests data from a specified resource
POST - Submits data to be processed to a specified resource
GET is basically used for just getting (retrieving) some data from the server. Note: The GET method may return cached data.
POST can also be used to get some data from the server. However, the POST method NEVER caches data, and is often used to send data along with the request.
The primary difference between a GET and a POST is that the POST will also submit the form data. In your example, you can use a GET by appending ?MyValue=<myValue> to your URL and WebAPI will assign the value to the Action's parameter.
If the GET request needs to work then use this code block:
function MyLoadData(myValue) {
$.ajax({
method: 'GET',
url: '/Home/GetMyData?myValue=test',
success: function (data) {
// Do Stuff
}
});
Basically, you can use GET or POST to get the data. but in GET, the data is passed through query string. In POST it can be passed both through query string as well as body.
One real world scenario when to use POST-Suppose your method expects Customer parameter and you need to send Customer object as parameter, then you can send the json representation of Customer object through body.but its not possible through GET.
One more reason is security,if you use GET, your method can be called through browser.but if you use POST, the method can't be directly called.
These were the important difference.For more differences see this link - http://www.diffen.com/difference/GET_(HTTP)_vs_POST_(HTTP)

jQuery multiple data decoding on server side

Scenario:
I have a jQuery.ajax call that is submitting three arrays to the server for saving to the database. I need to decode that combined data object that is being transferred to the server back into three arrays.
The server runs in php
If the scenario is ambiguous, what I am asking, how do you split the $input back into three arrays again. (This is on the php side.)
Expected results:
Breaking the object back into three seperate arrays for processing.
Current results:
Internal Server Error when I start to process the first array.
Note before we get to the code: I am still learning, please any tips/pointer are always welcomed.
Code:
jQuery.ajax
jQuery.ajax({
url: "save_all.php",
type: "POST",
dataType: 'json',
data: { grades: JSON.stringify($scope.grades), commutators: JSON.stringify($scope.commutators), sGrades: JSON.stringify($scope.sGrades)},
success: function (data) {
console.log(data);
},
error: function (data) {
console.log(data);
}
});
save_all.php
<?php
$input = json_decode(file_get_contents("php://input"), true);
$grades = $input["grades"];
$commutators = $input["commutators"];
$sGrades = $input["sGrades"];
You don't have JSON as the entire POST data, you have URL encoded key/value pairs, of which the values are JSON, so you don't need to access the raw POST data. Each of your JSON strings are in the standard $_POST array.
PHP:
$grades = json_decode($_POST['grades']);
$commutators = json_decode($_POST['commutators']);
$sGrades = json_decode($_POST['sGrades']);
Note: the dataType: 'json' in your ajax request refers to the response data type, not the request.

Issue posting a large amount of data when using json in a query string

I'm posting four JSON objects to the server using a jQuery ajax request. Each object can be up to 30k characters. When all of the parameters are large the last parameter or even the last two parameters do not show up on the server. Everything works fine when the parameters are smaller though.
In chrome's network tab I see all of the parameters in their entirety. In fiddler I see the parameters in their entirety but the parameters that don't show up on the server will not have a name.
Fiddler
The structure of my request is as follows:
var formData = "json0=" + JSON.stringify(json0) + "json1=" + JSON.stringify(json1); //etc
$.ajax({
type: 'POST',
url: url,
data: formData,
success: function (result) {},
error: function() {}
});
I wouldn't think there would be a limit on a POST but it's acting like the data is being truncated for some reason. Server side I'm in Java using ParameterAware to retrieve the data but I think the issue is before it gets there since fiddler doesn't have the parameters' names.
Query strings are not made for large amounts of data, you should pass your data to your Ajax call in an object:
$.ajax({
type: 'POST',
url: url,
dataType: "JSON",
data: {
json0: json0,
json1: json1
// etc
},
success: function (result) {},
error: function() {}
});
Have a look at this article discussing the maximum length of query strings.
jQuery AJAX documentation: http://api.jquery.com/jQuery.ajax/

How can I send an javascript object/array as key-value pairs via an AJAX post with easyXDM?

Recently I realized that I needed to use easyXDM instead of jQuery's $.ajax in order to make a cross domain post request. After getting easyXDM set up I see that the functions line up fairly closely:
jQuery:
$.ajax({
url: "/ajax/",
method: "POST",
data: myData
});
easyXDM:
xhr.request({
url: "/ajax/",
method: "POST",
dataType: 'json', // I added this trying to fix the problem, didn't work
data: myData
});
myData is setup something like:
myData = {};
myData[1] = 'hello';
myData[2] = 'goodbye';
myData[3] = {};
myData[3][1] = 'sub1';
myData[3][2] = 'sub2';
myData[3][3] = 'sub3';
When I make the request with jQuery it handles the sub fields properly, but not with easyXDM.
Here is how the POST request comes into the server with jQuery:
screenshot-with-shadow.png http://img37.imageshack.us/img37/4526/screenshotwithshadow.png
And here is how it comes in with easyXDM:
screenshot-with-shadow.png http://img204.imageshack.us/img204/4526/screenshotwithshadow.png
How can I send an javascript object/array of key-value pairs via an easyXDM / XHR request like jQuery does?
In light of the limitations of easyXDM discussed in the comments, the only way you can use it would be to serialize your data manually when passing it to .request i.e.
xhr.request({
url: "/ajax/",
method: "POST",
data: {jsonData: JSON.stringify(myData)}
});
Alternatively you could create your own postMessage solution but you will be excluding IE7 and below.
I think you are mistaken about sending a request cross-domain via AJAX. You CAN indeed send a request cross-domain via AJAX regardless of the JavaScript API. However, in order to receive a response cross-domain, the response needs to be of data type JSONP.
JSONP is simply JSON with padding, for example:
JSON:
{ Key: "Hello", Value: "World" }
JSONP:
callback({ Key: "Hello", Value: "World" })
It is a subtle difference but JSONP by-passes browser same-origin policy and allows you to consume JSON data served by another server.
To consume JSON data coming from another server via jQuery AJAX try this:
$.ajax({
url: "http://mydomain.com/Service.svc/GetJSONP?callback=callback",
dataType: "jsonp",
data: myData,
success: function(data) {
alert(data);
}
});
For this to work you must make sure that your web service is returning results as JSONP and not JSON.
As easyXDM can't serialize properly you need to serialize data manually:
JSON.stringify(myData)
Since the request will now contain a json string rather than object then Index.html should not parse the properties to create json structure. Go to index.html that comes with easyXDM and locate the following code:
var pairs = [];
for (var key in config.data) {
if (config.data.hasOwnProperty(key)) {
pairs.push(encodeURIComponent(key) + "=" + encodeURIComponent(config.data[key]));
}
}
data = pairs.join("&");
Don't execute this code in a case of POST request. Just assign config.data to data:
data = config.data;

Categories

Resources