Nodejs json string shows as [object Object] - javascript

Front End
// js / jquery
var content = {
info : 'this is info',
extra : 'more info'
}
$.ajax({
type: 'POST',
url: '/tosave',
data: content
});
Node
// app.js
app.post('/tosave', function(req, res){
fs.writeFile('/saved.txt', req.body, function(err, data){})
});
This saves to the file as [object Object]. I get the same result when I use JSON.stringify() on content before sending it through the ajax request. However, if I stringify it in node.js it successfully saves as {"info":"this is the info","extra":"this is extra"}.
My question is why this happens? Also, how would I go about converting it to a json string before the ajax request?

If you really want to send text (e.g. that happens to look like correct JSON, but isn't), and don't want Node to see it as JSON and convert it into an object for you, you could try specifying:
$.ajax({
type: 'POST',
url: '/tosave',
data: content,
processData: false
});
This will cause the data to be sent with application/x-www-form-urlencoded which might possibly prevent Node from helpfully turning the data into a JSON object.
However I would recommend simply stringifying req.body before writing it to the file. writeFile doesn't do this for you because you can send a buffer instead of a string, I suppose.

It seems like both jquery and node are being very helpful here.
Jquery recognises that you are sending an object and automatically converts into a format that can be transported before it sends it.
Node recognises what you are sending and decodes it when it receives it, turning it back into an object.
Basically this means that you don't have to worry about the transport.
What's not to like about that?

Related

How to make such a structure in javascript

I'm new to JS. And have a basic silly doubt. Please bear with me.I want to send a request of the form:
{"user":{"username":"myuser","password":"mypass","role":"myrole"}, "organization":"org_name"}
such that the user object can be access by req.body.user and organisation can be accessed by req.body.organization.
But when I'm sending this request:
it translates to-
{
"user[username]": "myuser",
"user[password]": "mypass",
"user[role]": "myrole",
"organization": "org_name"
}
When I just send
{"user":{"username":"myuser","password":"mypass","role":"myrole"}}
then I can access using req.body.user, but not the way mentioned above. Why is this so?
How can I send the request now such that I can access the request.body.user and req.body.organization properly?
EDIT:
This is how the request is sent. Front end: ember, backend node/express:
Ember.$.post("http://"+window.location.hostname+":3000/api/organizations/customer",{"user":{"username":"myuser","password":"mypass","role":"myrole"}, "organization":"org_name"},function(data){
console.log(JSON.stringify(data),null, " ");
});
Receiving side:
console.log(JSON.stringify(req.body,null," "));
I am trying to create the user but req.body.user is undefined. Though I can use user[username] and proceed, but that s now how I want to do
You aren't sending JSON to the server. Passing an object in as data doesn't send it as an object; it simply gets converted to a query string [source]. If you want to send JSON, you need to use JSON.stringify on the data that you send, not the data you receive.
Ember.$.post("http://"+window.location.hostname+":3000/api/organizations/customer",JSON.stringify({"user":{"username":"myuser","password":"mypass","role":"myrole"}, "organization":"org_name"}),function(data){
console.log(data);
});
With the help of Christian Varga's answer to this post, I could further dive in. Though the problem was still not solved, but it gave some insight of how can that be solved.
This is what I did next for such a structure. As per his suggestion, I used JSON.stringify but at a different place:
Ember.$.post("http://"+window.location.hostname+":3000/api/organizations/customer",{"user":JSON.stringify({"username":"myuser","password":"mypass","role":"myrole"}), "organization":"org_name"},function(data){
console.log(data);
});
On the backend server side I could then receive req.body.user. But the req.body.user was stringified JSON. To further access this inner JSON, I had to use JSON.parse.
Though this worked, but I was looking for more better solution, since this backend change worked for my front end implementation, but was failing for RESTClient.
I understood I need to pass the contentType of the data to be sent in the post request. I could not find $.post argument for contentType. So then I used $.ajax call.
Ember.$.ajax({
url: "http://"+window.location.hostname+":3000/api/organizations/customer",
type:"POST",
data: JSON.stringify({user:{username:username,password:password,role:role}, organization_id:organization_id}),
contentType: "application/json; charset=utf-8",
dataType:"json",
success: function(data){
console.log(JSON.stringify(data),null, " ");
}
});
where the username, password, role, organization_id are already assigned variables.

Consuming JSON with an array in ExpressJS

On the webpage I am POSTing some JSON using jQuery:
$.post('/url', data);
My data is a javascript object that contains some values and an array. JSON.stringify(data) looks like:
{"favoriteAnimal":"piglet", "okayAnimals":["cats","dogs"]}
I'm consuming this JSON in a NodeJS webapp using ExpressJS (which is wired up with the body-parser middleware). I can retrieve the favorite animal like req.body.favoriteAnimal and it gives me the string piglet which is all fine and dandy.
But how do I access the values in the array?
req.body.favoriteAnimal // piglet
req.body.okayAnimals // undefined
req.body.okayAnimals[] // syntax error
This works...
req.body['okayAnimals[]']
...but smells fishy. It also won't return an array if the original data that is being POSTed contains only one element in its array (it just returns a single string).
Is there something going on with the the jQuery encoding of the JSON or something going on with the decoding in ExpressJS that's preventing me from accessing it like req.body.okayAnimals and getting an array every time?
Kevin's answer almost got me there.
$.post('/url', JSON.stringify(data)) will send a string which is one step closer. Unfortunately jQuery's $.post sets the wrong header
Content-Type:application/x-www-form-urlencoded; charset=UTF-8
which ExpressJS's body-parser will not handle appropriately. You end up with
req.body={"{\"favoriteAnimal\":\"piglet\",\"okayAnimals\":[\"cats\",\"dogs\"]}":""}
I rewrote how I was sending the data.
$.ajax({
url: '/url',
type: 'POST',
data: data,
contentType: 'application/json; charset=utf-8',
dataType: 'json'
})
I saw that my browser was sending the correct headers
Content-Type:application/json; charset=UTF-8
And observed
req.body={"favoriteAnimal":"piglet","okayAnimals":["cats","dogs"]}
JavaScript objects and JSON are two very differen things, which is the root of the problem you are seeing. What you are passing to $.post() is actually an object, not json, and is therefore being converted to a paramstring by jQuery before being sent to node. In this case, the paramstring is:
favoriteAnimal=piglet&okayAnimals[]=cats&okayAnimals[]=dogs
which of course explains why an okAnimals[] property exists on the body.
I'm surprised that the middleware you are using to parse the body isn't picking that up properly, but regardless you should instead pass a json string to $.post if you want to send it as is.
$.post('/url', JSON.stringify(data));

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

javascript json request with some parameters

So a simple question:
JavaScript needs to send to server that request:
myserver/scipt.php?LANG=EN&AGENT={"Login":{"name":"user","pass":"user"}}
How I need to form url and data in Ajax?
Is this right?
var formData = {
"login":$("#field1").val(),
"pass":$("#field2").val()
};
$.ajax({
url:'http://myserver/scipt.php?LANG=EN&',
type:'GET',
data:'AGENT=' + $.toJSON(formData),
success: function(res) {
alert(res);
}
});
Thank you!
I'd recommend sending JSON via POST instead of GET. GET has some limitations that you want to avoid.
A part from that, yes, your code seems ok.
EDIT:
Sorry, your code is not ok.
Change the data line to:
data: $.toJSON(formData),
You need to send the data to the server in the form of a map ..
Your data is already in json format.. You need not do $.toJSON again
Instead of
data:'AGENT=' + $.toJSON(formData),
send it this way
data:{ 'AGENT' : {'Login' : formData } },
You need to URL encode any strings you want to pass through Ajax.
If jQuery works anything like a normal form, you also need to put all your query string data into data to avoid the existing query string being destroyed.
url:'http://myserver/scipt.php',
type:'GET',
data: {
"AGENT": $.toJSON(formData),
"LANG": "EN"
},
Note, you should use POST requests if you are transmitting user credentials. You don't want them cached or stored in server access.log files.

How to send data in request body with a GET when using jQuery $.ajax()

The service API I am consuming has a given GET method that requires the data be sent in the body of the request.
The data required in the body is a list of id's separated by hypen and could potentially be very large and thus it must be sent in the body otherwise it will likely foobar somewhere in the browsers/proxies/webservers etc chain. Note I don't have control over the service or API so please don't make suggestions to change it.
I am using the following jQuery code however observing the request/response in fiddler I can see that the "data" I am sending is ALWAYS converted and appended to the query string despite me setting the "processData" option to false...
$.ajax({
url: "htttp://api.com/entity/list($body)",
type: "GET",
data: "id1-id2-id3",
contentType: "text/plain",
dataType: "json",
processData: false, // avoid the data being parsed to query string params
success: onSuccess,
error: onError
});
Anyone know how I can force the "data" value to be sent in the body of the request?
In general, that's not how systems use GET requests. So, it will be hard to get your libraries to play along. In fact, the spec says that "If the request method is a case-sensitive match for GET or HEAD act as if data is null." So, I think you are out of luck unless the browser you are using doesn't respect that part of the spec.
You can probably setup an endpoint on your own server for a POST ajax request, then redirect that in your server code to a GET request with a body.
If you aren't absolutely tied to GET requests with the body being the data, you have two options.
POST with data: This is probably what you want. If you are passing data along, that probably means you are modifying some model or performing some action on the server. These types of actions are typically done with POST requests.
GET with query string data: You can convert your data to query string parameters and pass them along to the server that way.
url: 'somesite.com/models/thing?ids=1,2,3'
we all know generally that for sending the data according to the http standards we generally use POST request.
But if you really want to use Get for sending the data in your scenario
I would suggest you to use the query-string or query-parameters.
1.GET use of Query string as.
{{url}}admin/recordings/some_id
here the some_id is mendatory parameter to send and can be used and req.params.some_id at server side.
2.GET use of query string as{{url}}admin/recordings?durationExact=34&isFavourite=true
here the durationExact ,isFavourite is optional strings to send and can be used and req.query.durationExact and req.query.isFavourite at server side.
3.GET Sending arrays
{{url}}admin/recordings/sessions/?os["Windows","Linux","Macintosh"]
and you can access those array values at server side like this
let osValues = JSON.parse(req.query.os);
if(osValues.length > 0)
{
for (let i=0; i<osValues.length; i++)
{
console.log(osValues[i])
//do whatever you want to do here
}
}
Just in case somebody ist still coming along this question:
There is a body query object in any request. You do not need to parse it yourself.
E.g. if you want to send an accessToken from a client with GET, you could do it like this:
const request = require('superagent');
request.get(`http://localhost:3000/download?accessToken=${accessToken}`).end((err, res) => {
if (err) throw new Error(err);
console.log(res);
});
The server request object then looks like {request: { ... query: { accessToken: abcfed } ... } }
You know, I have a not so standard way around this. I typically use nextjs. I like to make things restful if at all possible. If I need to make a get request I instead use post and in the body I add a submethod parameter which is GET. At which point my server side handles it. I know it's still a post method technically but this makes the intention clear and I don't need to add any query parameters. Then the get method handles a get request using the data provided in the post method. Hopefully this helps. It's a bit of a side step around proper protocol but it does mean there's no crazy work around and the code on the server side can handle it without any problems. The first thing present in the server side is if(subMethod === "GET"){|DO WHATEVER YOU NEED|}

Categories

Resources