I have two Question which I am uncertain of.
What happens and what are the rules when using this piece of coding:
var c = "Test";
$scope.data = {c : c};
The output returns [object Object] and console shows this value Object {c: "Test"}
If this value is returned to a C# based service how can I extract the value c from the object correctly?
EDIT:
I am using WCF RESTful service and my url looks like:
$http.post("http://localhost/TestService.svc/testdata/" + $scope.data)
When you do a POST to a service you should send the data as post data, as described in the docs for $http.
var url = "http://localhost/TestService.svc/testdata/";
var postData = { c: "Test" };
$http.post(url, postData);
Remember to configure your server action with Method="POST" to be able to receive POST data. The deserialization from the posted data is handled by WCF.
Another option is of course to use a PUT method, and append your data as query parameters to the URL. The URL would in that case look something like
http://localhost/TestService.svc/testdata/?c=Test
If you have nested data in your model this will soon get tricky to handle though, and in that case a POST is the better option. Also; If you use PUT, remember to not expose your service to CSRF vulneratibilities in which an attacker gives a link to an authenticated user which then performs some unwanted actions.
When you try to convert an object to a string (which happens when you try to display it), you get the text [object Object], indicating that it is an object without any further disclosure of its properties.
When you want to pass the data to other applications, a common format is JSON, which looks like the string your get in the console. C# as well as most other modern languages have built-in functionality or libraries to parse JSON into their own data structures.
To explicitly convert an object to JSON, use JSON.stringify.
var c = "Test";
var data = {c : c};
alert(JSON.stringify(data));
You're a little short on details in your question. Is this AJAX? Form postbacks? URL parameters? Headers? Websockets? How are you sending this data to the server? My answer assumes you're doing AJAX with the content in the body of the request.
It's important to understand that "returning to a C# service" isn't a problem. Whenever you make an HTTP request, you're serializing the data in a certain way. Probably in this case you're serializing it to JSON. The server reads the request, parses the JSON, and makes its own interpretation of it. So as long as you generate valid JSON (which your libraries will certainly do behind the scenes), the server won't know exactly how you generated it.
Secondly, JSON serializers don't all follow the same convention. JS is perfectly happy to have a key not be quoted, which is what you're observing.
foo = {
abc: 123, <--- "abc" is a literal string here, even if it isn't quoted
"abc": 456 <--- same key, different value
}
Most other language libraries require key strings to be quoted, JS doesn't.
So to answer your question "how can i extract the value c", the answer is, just like any other key! Assuming you deserialize the request body to a variable called data, then you'd just do data["c"].
console.log($scope.data + ""); // [object Object]
console.log($scope.data); // the actual object
If an object is coerced to a string, like in the above example.
If .toString(); is called on an object.
[object Object] is displayed.
Related
I want to be able to parse external variables into a JSON object.
Something like this would do:
var username = "zvincze";
And using that variable to parse a JSON object:
var json = '{"username":"VARIABLE_GOES_HERE"}'
var obj = JSON.parse(json);
This is a very simple question that I can't seem to figure out. In fact, I don't even know if there's a way to actually acheive something such as this.
You need to distinguish carefully between JSON and JavaScript objects. They are two entirely different things.
JSON is a language-independent character-based data representation that is used for data interchange. For instance, if you are sending data to a server, it needs to be in string form, so you would need to convert your data into JSON. If you are receiving data from a server, and it is JSON format, you need to convert it into a JavaScript object so you can use it in your JavaScript program.
JSON actually has nothing to do with JavaScript. For example, JSON could be used as a string-based data representation for Java programs exchanging data. Java and pretty much all other languages provide their own library routines for converting their native data into JSON and vice versa.
The only relationship between JSON and JavaScript objects used in JavaScript is that a JSON string looks much like a JavaScript object literal, with some additional restrictions, such as that keys must be quoted, that it cannot hold certain data types such as functions, and that it cannot hold circular references.
The "JS" part of "JSON" does not indicate that JSON is a basic JavaScript data structure, or that JSON is used in JavaScript for representing or manipulating data. It merely comes from the fact that, as mentioned above, the format of a JSON string is loosely modeled after that of a JavaScript object literal.
In normal day-to-day JavaScript programming, you will never use JSON, and don't need to worry about it. You will need to worry about JSON only when, as I said, you are sending data to somewhere, or receiving data from somewhere, that expects JSON as the data format. That is the case when making ajax calls, of course, but actually, even then, since jQuery's $.ajax will automatically convert data to and from JavaScript objects if you tell it the right types, even in that case you do not normally need to worry about JSON.
Note by the way that JSON can represent primitive values, not just JavaScript objects. For example, "1" is valid JSON which represents the number 1.
As I understand your question, you want to create a JavaScript object (not JSON) which contains as one of its values that of the variable username. You create a JavaScript object with regular old JavaScript object literal format, in this case
{username: username}
This means, create an object, with a single key named "username" (quote it if you please), whose value is that of the variable username. Again, unless you plan to send this object somewhere that expects a JSON string representation, there is no need to even think about JSON in this case.
In theory, yes, as one answer suggested, you could create a JSON string with the value of username "interpolated", using string arithmetic like '{"username":"' + VARIABLE_GOES_HERE + '"}', and then convert that JSON string into a JavaScript object using JSON.parse. However, there is absolutely no reason to jump through these hoops, when you can simply write the JavaScript object as a normal JavaScript object literal.
Another answer shows a way to define a regular JavaScript object, and then turn it into JSON using JSON.stringify. However, again, in your case, there is no need to do this unless you are planning to send the object somewhere.
Yet another answer shows a way to define a regular JavaScript object, then stringify it into a JSON string, then immediately parse it back into a JavaScript object, which will be exactly the same object you started with before stringifying and parsing. There's absolutely no need to do this.
One sees no small number of questions on SO trying to somehow manipulate or search or replace within JSON, using regexps for example. There are almost no cases where you need to even think of doing such a thing. JSON has two fundamental operations: converting values into JSON, and converting JSON into values. Both of those are built into the language in the form of JSON.stringify and JSON.parse, that do their jobs with absolute reliability and performance. If for some reason you need to modify data which is in JSON string format, don't manipulate the string; all you need to do is parse it into a JavaScript value, manipulate the value, and then convert it back into JSON.
Unfortunately, for unknown reasons, many JavaScript programmers who are learning the language, including many who have posted questions here on SO, have developed the misperception that JSON is a JavaScript object, or that they must think about JSON and stringifying and parsing in order to deal with plain old JavaScript objects, which is very much not the case.
Minor point, but you use the term "parse" in your question. I see more and more people using this word for some reason to mean "access" or "retrieve" or "extract". Actually, "parse" has a very specific meaning: to analyze a string-based representation of information (such as a program or data object), according to a particular grammar, into some suitable computer-friendly form for further processing. What JSON.parse does is parsing in this sense, because it is analyzing a string-based representation of information according to the JSON grammar into a JavaScript object for further processing.
You can simply concatenate strings like below...
var json = '{"username":"' + VARIABLE_GOES_HERE + '"}'
in your case:
var username = "zvincze";
var json = '{"username":"' + username + '"}';
Happy coding....
I think what you're doing is sort of odd. The object you create is json by definition (JavaScript Object Notation).
var obj = {};
obj.username = "zvincze";
//obj is now json
var str = JSON.stringify(obj);
//str == {'username':'zvincze'}
JSON.parse(obj) should fail since obj is already json.
Without messing with concatenation var json = '{"username":"'+ userName +'"}' you can:
var ob = {}; // or simply: var ob = {username:"zvincze"};
ob.surname = "Zvincze";
ob.name = "Zachary";
ob.id = "5182842";
var json = JSON.stringify(ob);
var obj = JSON.parse(json);
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/JSON
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
var json = JSON.stringify({username:"zvincze"})
I have objects that I serialize into JSON strings on the server side for consumption by my JavaScript code. I then deliver these to the client along with the HTML content so that they are immediately available. I had been writing them into the response as strings that I then parse with JSON.parse, like this:
var json = "{ \"someKey\":\"someValue\" }"; // This string written in by server-side code
var parsed = JSON.parse(json);
Then it occurred to me that this is a waste of time, since I could just directly write the JSON string as a literal JavaScript object, like this:
var someObject = { "someKey" : "someValue" }; // This literal written in by server-side code
This saves the step of escaping the quotes in the string, followed by the step of parsing it back to an object.
I control the JSON rendering on the server side, and I never deliver strings that users have supplied. This seems like a no-brainer. But are there any gotchas to look out for -- any maximum sizes for JavaScript literal objects or anything like that?
I have a website that returns a JSON-like data structure like this:
{
"name":"tom jones",
"no": 123,
"storedproc": function(){
callbuyer(0123);
}
}
I'm getting this data using $.ajax() with dataType "JSON". Unfortunately, my $.ajax() calls the error callback because my data contains a function().
How can I parse this correctly? I really need to store the function in a variable and call it later.
That is simply not legal JSON (as you know given the title of the question) See the offical JSON syntax. The nice thing about real JSON is that one can use JSON.parse which safely wraps an eval call.
While eval could be used, I would suggest revisiting the architecture of your application and find some other way to do what you are trying to do.
In particular, I would have the server return the 0123 only, and let your client keep the logic that lets it know, in certain cases, which functions apply (in the scenario here, the function would be callbuyer).
This should work because you say you want to call the function which is the value of the storedproc later. Since the body of this function contains a call to callbuyer it follows that your client side script knows what callbuyer is. The trick is for your server not to send back arbitrary, unconstrained functions, but rather data that your client can exploit somehow using the knowledge it has about the overall application.
Could you arrange to have the server return JSON like this:
{"name":"tom jones",
"no": 123,
"storeprocFn": callbuyer,
"arg": "0123"};
Then your callback function can call the callbuyer function and pass arg
Use eval to interpret the string as a javascript object. You won't be able to use the JSON data type though. I believe what you need to do is use 'text' as the dataType for the $.ajax call. Then do something like:
var data = eval('(' + text + ')');
Should work. Of course, eval is evil. But it would solve your problem. As long as you can guarantee there isn't anything malicious in the text (no unsanitized, user entered data) then you should be ok.
AFAIK, functions are left out when using JSON.stringify, it's just not meant to be used to clone full objects (props and methods). However, you might be able to pass the function body as a string.Say you decide on a string format like func=>var foo = 'bar'; return foo;. This should be passed as a regular JSON string, after parsing the object you could then iterate all properties, and convert those strings to functions like so:
for (var prop in parsedObj)
{
if (parsedObj.hasOwnProperty(prop) && parsedObj[prop].match(/^func\=\>/))
{
parsedObj[prop] = new Function(parsedObj[prop].replace('func=>',''));
}
}
Though, seriously, I'd say you might want to rethink your approach, this is not what JSON is for. It's unsafe, all JSON strings are eval'ed, after having made sure they contain no harmful code. This approach is creating a loophole/vulnerability that the JSON people worked hard for to seal off.
For your example will this work:
'user.storeproc = function() { callbuyer( user.no);};'
The Var 'user' is the object of the parsed json.
Ps: maybe you have to format user.no, from 123 to 0123
Following JSON extension, "JFON", does transport of functions and array-properties.
JFON uses eval and is intended for case if:
1) your data is from trusted source ( like not-derived from user input or is a code from your own server), and
2) you know there are no undesired side effects with context of "eval"
(it is a context of eval in function "fromJFON", line 127 )
3) it is costly to refactor your app to use "functionless" JSON;
4) JFON is one-day work, so may be needs more testing;
The idea: use selected property name to escape functions and arrays like
in strings when selected character "\" is used to pass \n and \ for itself.
In JFON, name "wrap" is selected to pass functions and itself: "wrap" : { "fun" : ... and "wrap" : { "esc" : ...
demo: http://landkey.org/Sandbox/z/spaceen86/js/btb/tests/jfon.htm
code ( use commit 0.0.86 ):
https://github.com/lancelab/spaceen/blob/master/js/btb/JFON.js
test: github.com/lancelab/spaceen/blob/master/js/btb/tests/jfon.htm
Here is another, "JWON" extension: JSON-comments, here-documents, monkey-patching of JSONs:
github.com/lancelab/Boardspirator/blob/master/diary/play/tp/jwon.js
I have a json object with a function:
var thread = {
title: "my title",
delete: function() {
alert("deleted");
}
};
thread.delete(); // alerted "deleted"
thread_json = JSON.encode(thread); // convert to json from object
thread_object = JSON.decode(thread_json); // convert to object from json
thread_object.delete(); // this didn't work
After I converted it back from json string to object, I could not use delete() function.
When you convert something to json, the functions are gone?
Are there ways to keep them in the json string?
I'm using Mootools.
You got it. Take a look at that JSON.encode output. Only simple data types are allowed in JSON representations, partly for ease of creation, and partly for security. (The reason we use something like JSON.decode instead of eval is the possibility of embedding functions.)
You'll have to modify the JSON library source code to accept functions, or write your own in order to preserve the literal definition of the object upon conversion to string.
Consider, though, the possibility that you don't really need to do this. There's probably a better solution, but I can't begin to address that without knowing your exact situation.
I'm using JSON to communicate some data through AJAX from the backend to the frontend (Javascript, of course). The XMLHttpRequest is done by a Prototypejs-written AJAX-handler (I'm still in the process of migrating to jQuery, but the noConflict-mode allows me to run both simultaneously), after which PHP sends the X-Json header with some data like objects = {'foo': 'bar'}.
The Prototypejs-Ajax.Request passes a json variable to the onSuccess-callback, containing all the JSONdata, so the processing isn't the hard part. However, I noticed that since the JSON is automatically evaluated, the objects variable is made global (and thus a member of the window object.
I know it's not really a problem since it's just an unused variable, but I always tried to stay away from global variables as much as possible. Additionally, the datasets may be pretty large on some occasions, so it'll just be a huge duplicate variable of which one is never used. So, if possible, I'd rather lose the global.
My question: how? If there's a good reason for this happening, or if this is just a Prototypejs-specific issue, or if this just indicates I'm doing something very wrong, please tell me :-)
Thanks!
Are you sending back objects = {"foo":"bar"} from PHP? When sending JSON, you just send {"foo":"bar"} and get the data as the return result of eval:
var json = '{"foo":"bar"}'; // This string would really be coming from PHP
// ...
var objects = eval('(' + json + ')'); // objects variable will be limited to the
// current scope.
If, for some reason, you must evaluate objects = ..., you can limit the variable to the current scope before running eval:
var objects;
eval('objects = {"foo":"bar"}');
Note that the PHP functions json_encode and json_decode will create "proper" JSON for you, which means it will use double quotes, and it will not use any kind of assignment (True JSON is limited to an array/object as the outer-most value, and it may not contain assignment or function calls. See the JSON specification.)
If the PHP is outputting objects = {'foo': 'bar'} then it isn't outputting JSON. JSON can't include the '=' character outside a string and uses the double quote character not the single quote. This means it is outputting JavaScript.
You have two options here.
The first is to try to restrict the scope of the JavaScript, the second is to fix the PHP so it outputs real JSON.
I would recommend the second option. Deal with JSON not JavaScript.
If you want to try to restrict it, then you need to limit the scope somehow. Possibly with:
function () {
eval("var " + php_generated_code);
doSomethingWith(object);
}
… although I'm not sure what the scope of eval() is.