I am trying to POST JSON to a Node app, which will simply return it via a GET. Client side, I generate a JSON string of the model, and POST it to the server:
$.post(serverURL, ko.mapping.toJS(viewModel), function(data) {}, "json");
This yields a string that looks like:
{"switches":[{"id":1,"name":"Living Room","state":false},{"id":2,"name":"Dining Room","state":false},{"id":3,"name":"Kitchen Room","state":true},{"id":4,"name":"Aviary","state":true}]}
Note that the "state" values are unquoted true/false, which is valid JSON. On the server, if I log the request body, I get the following:
{ switches:
[ { id: '1', name: 'Living Room', state: 'false' },
{ id: '2', name: 'Dining Room', state: 'false' },
{ id: '3', name: 'Kitchen Room', state: 'true' },
{ id: '4', name: 'Aviary', state: 'true' } ] }
Note the differences:
My goal is to simply store the original JSON object in it's original string format, for a GET request later. What is doing this formatting, and how can I prevent it?
Additional info per request
My Node.JS code is as follows:
var express = require('express');
var app = express();
var model;
app.configure( function () {});
app.use(express.bodyParser());
app.get('/', function (req,res) {
res.setHeader('Content-Type', 'application/json');
console.log(model);
res.send(model);
});
app.post('/', function (req,res) {
res.header("Access-Control-Allow-Methods", "POST");
res.setHeader('Content-Type', 'application/json');
model = req.body;
console.log(model);
});
app.listen(3000);
I see a couple of issues:
Your post
call is not telling the server what kind of data you're sending. In particular, the last argument to post
(dataType
, for which you're supplying 'post'
) is not the format of the data you're sending to the server, it's the format of the data you're expecting back from the server.
Separately, you're using KnockoutJS's toJS
function. According to the documentation, this doesn't produce JSON, it produces a JavaScript object graph. To get a JSON string, you need to use ko.toJSON
.
So my guess (and it is that) is that Express doesn't have enough information to work with and is applying the wrong decoding mechanism, and the data being sent is getting a bit mangled by jQuery trying to turn it into form data.
Try using the ajax
function and specifying contentType: "application/json"
and using ko.toJSON
, e.g. something like:
$.ajax({
type: 'POST',
url: serverURL,
data: ko.toJSON(ko.mapping.toJS(viewModel)),
success: function(data) {},
dataType: 'json' // IF you're expecting JSON back
contentType: 'application/json'
});
(Or possibly just data: ko.toJSON(viewModel)
, I'm not deep enough into Knockout to know for sure.)
I had the same problem I think, and got around it by calling JSON.stringify on the request body. If anybody has a more proper solution I'd like to hear it, because this seems a bit weird. But OTOH it works 8P.
My controller produced these logs:
------ req.body here ----------
[ { name: 'My Watchlist',
stocks: [ 'AACC', 'AAPL', 'VZ', 'JPM' ] } ]
------ stringified req.body here ----------
[{"name":"My Watchlist","stocks":["AACC","AAPL","VZ","JPM"]}]
---- end ------
With this code at the start of the controller
console.log('------ req.body here ----------');
console.dir(req.body);
console.log('------ stringified req.body here ----------');
console.log(JSON.stringify(req.body));
console.log('---- end ------');
try{
var o = JSON.parse(JSON.stringify(req.body));
}
catch(e){...