Strange behavior when sending JSON over AJAX - javascript

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");
}
});

Related

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

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.

400 error "You must pass a valid patch document in the body of the request." [duplicate]

So according to the jQuery Ajax docs, it serializes data in the form of a query string when sending requests, but setting processData:false should allow me to send actual JSON in the body. Unfortunately I'm having a hard time determining first, if this is happening and 2nd what the object looks like that is being sent to the server. All I know is that the server is not parsing what I'm sending.
When using http client to post an object literal {someKey:'someData'}, it works. But when using jQuery with data: {someKey:'someData'}, it fails. Unfortunately when I analyze the request in Safari, it says the message payload is [object Object] ... great... and in Firefox the post is blank...
When logging the body content on the Java side it literally gets [object Object] so how does one send REAL JSON data??
Has anyone had experience with a Java service serializing JSON data in the request body, with the request sent from jQuery?
BTW here is the full $.ajax request:
$.ajax({
contentType: 'application/json',
data: {
"command": "on"
},
dataType: 'json',
success: function(data){
app.log("device control succeeded");
},
error: function(){
app.log("Device control failed");
},
processData: false,
type: 'POST',
url: '/devices/{device_id}/control'
});
An actual JSON request would look like this:
data: '{"command":"on"}',
Where you're sending an actual JSON string. For a more general solution, use JSON.stringify() to serialize an object to JSON, like this:
data: JSON.stringify({ "command": "on" }),
To support older browsers that don't have the JSON object, use json2.js which will add it in.
What's currently happening is since you have processData: false, it's basically sending this: ({"command":"on"}).toString() which is [object Object]...what you see in your request.
Seal them up
//contentType: false,
//processData: false,

Sending JSON as a parameter value for post

Here's what I'm trying to accomplish:
User enters JSON in a textarea element.
{
"test":[
{"a":"b"}
]
}
Client side JavaScript parses the JSON.
myObject = $.parseJSON($("#my-textarea").val());
JSON is sent over an ajax post request to the server with
dataType: json,
data: {"my_object": myObject}
Post parameters are checked on the server side in sinatra and the JSON looks like this now.
{
"test": {
"0": {
"a": "b"
}
}
}
I'm wondering why the test array was changed into a hash and if there's anything I can do to avoid that. I'm thinking that the original JSON is improperly formatted, but I'm unsure.
EDIT:
Here is a stripped down version of the ajax request and controller action.
function test() {
return $.ajax({
url: "/test",
type: "post",
dataType: "json",
data: {"test":[{"a":"b"}]},
success: function(response) {
}, error:function(jqXHR,exception) {
ajaxError(jqXHR,exception);
}
})
}
post '/test' do
puts params
return {}
end
I would stringify the resulting JSON object before you send it, like this:
dataType: json,
data: {"my_object": JSON.stringify(myObject)}
If you have to support browsers that don't have JSON natively, you can conditionally import the json js to add that support. (jQuery does not natively have a JSON stringify method).
Try this
var test = "{ \"test\":[{\"a\":\"b\"}]}"
$.parseJSON(test) // or even JSON.parse(test)
If you trace the object before it goes to the server side you will confirm that it was parsed correctly. So the problem is in sinatra I would say.
Just first check what's the parse result before doing the server call.
If you don't know if it's your client doing the bad translation, create a native javascript object (without the parse) and send it instead. If it's still bad, I doubt the problem is on the client.
Output I got on the chrome console:
JSON.parse(test)
Object {test: Array[1]}
test: Array[1]
0: Object

how to parse following JSON data using Jquery

I am new on JQuery. I have this JSON response from the server how could I parse it?
[
{
"note": {
"created_at": "2012-04-28T09:41:37Z",
"updated_at": "2012-04-28T09:41:37Z",
"text": "aaaaaaaaaaafdafasd fasfasd dfa sdfasf asdfa fasdfda",
"lng": 44.5159794497071,
"id": 7,
"deleted": false,
"user_id": 1,
"note_type": "text",
"lat": 40.1884140543842
}
},
[ ... more JSON ...]
]
How could I parse this?
You have to set the data type of the request to "json", and the data will be already parsed in your success callback.
Everything you need to know at the moment is on http://api.jquery.com/jQuery.ajax/
Here is a very simple example of what you can do:
$.ajax({
url: url, // the service URL. Must answer proper JSON
data: { // the parameters of the request. This should be adapted to your case
param1: value1,
param2: value2
},
dataType: "json",
type: "POST",
success: function(resultData) {
// here, resultData is your parsed json
},
error: function() {
// handle error here
}
});
jQuery.parseJSON
Use this jQuery method to parse JSON objects.
If the server outputs actual JSON (the example in the question has errors) and it has the correct content type (application/json rather then the text/html that PHP defaults to) then you don't need to do anything.
jQuery will parse it for you (and present you with a JavaScript object in the success handler).
That's not JSON. What you have posted looks like a PHP array that had brackets wrapped around it to try to make it into JSON.
Use this site to validate your JSON in the future.
Now, to get your PHP array into JSON, use json_encode() and dispatch it to the browser with a specific header.
$array = array( 'test' => 'sure' );
header('Content-type: application/json');
print json_encode($array);
exit;
Now, you'll have actual JSON with which you can use in JavaScript.
$.get( 'yourFile.php',
function(data){
console.log(data);
}
);

Ajax message best practices

Say I need to use ajax to asynchronously ask the server for an xml file containing relevant data. What is the best practice on what this message should look like? Should it be a string like get_data or something similar? Should it be xml? I don't really need long polling since its a one-time (or close to it) request.
Thanks.
You can use standard a HTTP Post or Get to send the request to your server. If you don't need to specify any parameters to your server side script ( user_id, etc ) then simply appending get_data as a url parameter will work fine.
http://www.domain.com/script?get_data
If you need to send any parameters to the server in order to retrieve data it is best to encode the parameters in JSON or XML and send them as the data portion of your AJAX request. With JQuery and JSON data:
$.ajax({
type: "GET",
url: "http://www.domain.com/script",
data: { key: "value", key2: "value2" },
async: true,
dataType: "json",
success: function( data, textStatus ) {
someCallbackFucntion( data );
}
});
The message should be the url.
For example: http://www.example.com/get_data could return the data you need in the format you need (xml, json).
If you need some other data, use an other url. http://www.example.com/someotherdata
It really depends on the purpose, if everything else is XML, go for XML. Personally I perfer JSON (for the client-side at least).
In a recent implementation I made, I used a simple POST request where the key represented the type of data and the value contained the time-interval it should return.
Which could be (jQuery):
$.ajax({
type: "POST",
url: "http://www.domain.com/script",
data: { stock_value: "last_30_min", group_activity: "last_20" },
async: true,
dataType: "json",
success: function( data, textStatus ) {
someCallbackFucntion( data );
}
});
A server-side controller would then handle the request appropriately and the client-side would know what data to expect when it returned. Also the key and value would be humanly readable from both client- and server-side. Of course the time-intervals could be a timestamp or otherwise, whatever fits the need.

Categories

Resources