How to convert string into object property? - javascript

I have a json data that has unknown objects like this:
var x = {
"unknown1": 234,
"unknown2": 324
}
I can get the properties name as:
var prop1 = Object.keys(x)[0];
Now I want to find the value of this property. I can obviously do x[prop1], but I wanted to do x.prop1. My question is:
What are ways to convert prop1 into an expression so that I could use x.prop1?
If eval can solve this then how and why would eval create security problems in this case?

What are ways to convert prop1 into an expression so that I could use x.prop1?
You can't, without generating source code and compiling/evaluating it.
If eval can solve this then how and why would eval create security problems in this case?
Yes, eval (and its close cousin new Function) can do this. It's only a security issue if what you're evaling comes from an untrusted source. If you can trust that the value of prop1 doesn't contain malicious content, then you can use eval("x." + prop1) to do this. Or new Function("x", "return x." + prop1)(x).
But there's no good reason to. Just use x[prop1]. That's what brackets notation is for. It's normal practice, it doesn't have to fire up a parser and code generator, it's faster, and you don't have to worry about prop1 having malicious code in it. If you use eval or new Function, it's not normal practice, it has to fire up a parser and code generator, it's slower, and you have that niggling concern in the back of your mind. So use x[prop1]. :-)

As #mhodges says in his comment you could add a new property.
but it might seem redundant to do so.
x.prop1 = x[Object.keys(x)[0]]

Related

How to parse a string into javascript object?

I have a javascript object defined inside a string variable:
const str = "{a:1}";
I wonder what is the best way to convert it to a javascript object. I have searched a lot but all I found is to use JSON.parse or JSON.stringify to convert the string. But the tricky part in this string is that it is not a JSON object. The a is not quoted. I have tried below approach but it doesn't parse it to a object:
JSON.parse(JSON.stringify(str))
I know I can parse the string manually but I am looking for a more generic solution which support parsing all possible javascript object string.
var obj = eval(str);
Just be aware that using eval can have performance and security impacts.
If you don't control the content of str, i.e. it is a user input or it comes from a server you don't trust, the are risks.
Also, the JavaScript runtimes optimizes your code at runtime, but often disable many optimizations when engineering an eval.
Try to wrap the evaluation statement in a self invoked function that receive the variable passed to theeval:
(function(s) {
return eval(s);
}(str));
It ensures the creation of a closure to isolate the eval, mitigating it's potential impacts.
And last, don't take anything I've just said as an absolute truth: benchmark your code with and without the eval, just to be sure.

Use string variable to access value of object

I have a text input.
I want the user to be able to fill out a value in that text input like some of these examples:
results[0].address_components[0].long_name
results[0].formatted_address
fo.o[0].bar (where fo.o is a single key)
etc. (pretty much literally anything)
Then I want to take that value and use it as a key on some parsed JSON. So like...
$.parseJSON('data.json').results[0].address_components[0].long_name would return something like San Francisco.
How can I do this?
If I save the input value as a variable, say selector, and then try $.parseJSON('data.json')[selector] it just comes back undefined.
If I try to regex the selector and convert all instances of [ into . and remove all ] and split at . then reduce, then selectors like fo.o (one key) will break...
Thanks in advance!
You should generally set the results of parseJSON to a variable, rather than parse it every time you access it. parseJSON is generally going to go down to C code (depending on the environment), but it will still be really inefficient to call it over and over.
var res = $.parseJSON('data.json');
From there, you can access it like you would any other JavaScript object:
res.results, which is identical to res["results"] (which, in your case appears to be some kind of array).
A string key with special characters (., -, and pretty much anything non a-zA-Z0-9) is always accessed via the second form: res["fo.o"].
Note that this chains, so you can access res["fo.o"]["bar"] exactly as you'd address res["fo.o"].bar.
I would recommend using a JavaScript library like lodash for this (if this is feasible in your project, otherwise looking at its implementation might help):
It provides a large set of utility functions. The get function does exactly what you are looking for, namely it resolves a path on an object.
Sample code (assuming _ is your lodash reference):
var path = 'results[0].address_components[0].long_name'; // the user input
var data = $.parse('data.json');
var result = _.get(data, path); // resolves the path on the data object
As for the fo.o property name, I doubt there would be an easy solution, as this essentially makes your syntax ambiguous. How would you distinguish between a property fo.o and fo?
use eval. You would put everything as a string. So just concatenate strings based on the input. Then eval it. for example:
var str = "$.parseJSON('data.json').results[0].address_components[0].long_name";
and then eval it at runtime.
var result = eval(str);

Alternative to eval() javascript [duplicate]

This question already has answers here:
What are the Alternatives to eval in JavaScript?
(11 answers)
Closed 7 years ago.
I work mainly with javascript, Jquery, knockout, etc
The thing that attracted eval() to me is
var a = 5;
var b = 10;
eval("a+b");
//Gives me output 15
Note: I work in cases where the value of a and b changes dynamically
In my work I'm dealing with a lot of dynamic objects from json, knockout, etc. So eval solves most of my problems.
But as I read I found there are so many issues with eval() like slowing down etc.
I searched a lot and haven't found any substitute for eval() when i have to evaluate equation obtaining as string into equation as object.
Can anyone suggest a plugin or function alternative to eval() keeping in mind the example i have given above
Problem:
I'm creating a Table from Json data using knockout mapping. So that what ever the format of json is the table is generated. I also calculate some field using knockout computed.
Right now I use hard-coded
self.Salary = ko.computed(function(){ return self.salaryEqn() && eval(self.salaryEqn()).toFixed(2); })
self.salaryEqn(salEqnTxt);
I want to execute these equations dynamic. I can create it dynamicaly as string but to eval them is the issue I'm facing.
I want solution for
Is there a way to calculate a formula stored in a string in JavaScript without using eval?
Like a formula
"self.Salary = ko.computed(function(){ return self.salaryEqn() && eval(self.salaryEqn()).toFixed(2); })"
Javascript is a very flexible language in this regard. There are very very few cases where eval() is the right answer to any given question, and it certainly isn't necessary here.
If your a and b variables are part of an object, you can access them with string subscripts:
ie myobj.a could also be referenced as myobj['a'].
From that, you can use a variable for the subscript, and thus you can reference any element in myobj dynamically -- ie:
var myobj = {a : 5, b : 10};
var dynamicProperty1 = 'a';
var dynamicProperty2 = 'b';
//gives 15.
alert( myobj[dynamicProperty1] + myobj[dynamicProperty2] );
No eval() required. You can build the dynamicProperty strings however you wish, so there's virtually infinite flexibility.
If your a and b variables are globals, JS globals in the browser are actually children of the window object, so you can still use this technique even with globals.
ie your global variable a could also be accessed via window.a or window['a'], with the latter option allowing you to do the same dynamicProperty trick described above.
Hope that helps.
do you mean that you want to calculate an equation that you can't know until you've received it?
if so see Calculate string value in javascript, not using eval .
in short:
eval CAN be used sometimes, but only if the equation string comes from a trusted source, and there you need something like evaluating dynamic equations.
maybe using window['var' + num] might be more useful for you. i don't quite understand your question sorry.
If you can collect them under an object like root = {a: 1, b: 2}, then
Object.observe(root, function(newValues) {
res = newValues.object.a + newValues.object.b;
});
can keep your res variable up to date whenever the a or b changes
It looks like you are trying to do dynamic equations created by a user.
For example it could be 'a+b+c' or 'dog+cat', and you don't know.
The best way to handle user-input equations like that is to parse the text into tokens and then translate the tokens into values/operands.
That's a lot of work, but there are pre-rolled solutions. For example, math.js
Check more alternatives to eval in this question and another one here which both might be considered a duplicate...
I understand this is a link only answer, but it will for sure be helpful to others searching for alteratives to eval.

Javascript security question / Using eval()

I'm seeing code in the following form - is such use of eval() safe?
function genericTakeAction(frm_name,id,pagenum,action)
{
var rset=eval("document."+frm_name);
var x=eval("document."+frm_name+".edit_key");
var y=eval("document."+frm_name+".cAction")
if(x)
x.value=id;
if(y)
y.value=action;
page_list(pagenum);
}
Its used as:
<a href="javaScript:;" onClick="genericTakeAction('frmSearch',
'<?php echo $rec_id;?>','<?php echo $pagenum?>','makeOpen')"
class='link6'>Make Open</a>
Whether it's right or wrong, it's needlessly complicated.
function genericTakeAction(frm_name,id,pagenum,action)
{
var rset = document[frm_name];
var x = rset.edit_key;
var y = rset.cAction;
if(x)
x.value=id;
if(y)
y.value=action;
page_list(pagenum);
}
This works because in JavaScript, you can access an object's properties in one of two ways: Either using dotted syntax and a literal identifier, e.g. x = obj.foo;, or using bracket syntax and a string identifier, e.g. x = obj["foo"];. (Note how foo was not in quotes in the first one, but was in quotes for the second; but both do exactly the same thing. Also note that since the property name is a string in the second case, you can use any expression that results in a string, so y = "f"; x = obj[y + "oo"]; also works.)
P.S. It's wrong
eval() is generally frowned upon because, as you are already aware, it is considered unsafe.
In the browser environment, however, it is less of an issue, because in fact, any user could eval() any code they wanted to, using tools like Firebug, etc.
There is still an issue, in that the eval() embedded in the code can be run without the user knowing that he was triggering an eval(), but it's still much less of an issue than in a server-side environment like PHP.
eval() is actually typically used as you've shown to run JSON code being returned from a server-side request. Newer browsers can import JSON more safely using a dedicated JSON parse() function, but older browsers do not have this function and are forced to use eval() for this. Most JSON libraries have eval() in their code somewhere for this reason, but will generally do some sanitisation of the input before running it through eval().
Even if it might look a little bit convoluted, as others have already mentioned, from a pure security perspective, you have to make sure that the 'frm_name' parameter of the genericTakeAction() function can never contain user-supplied data.
In your example, the 'frm_name' parameter contains the hard-coded literal 'frmSearch'. So it is ok as long as this genericTakeAction() function does not get called somewhere else with user-supplied data for the 'frm_name' parameter.
See http://en.wikipedia.org/wiki/Cross-site_scripting#Traditional_versus_DOM-based_vulnerabilities

Evaluate the string as object (javascript)

Here is the problem string:
$.ajax(......
,success:function(msg){
var obj = eval('['+msg.d+']');
},
....
}
msg.d contains something like:
new Person(2, 'Name Surname','This is just string came from Par'is at Sat'urday');
How can pass the javascript problem ?
If the string really is as you've quoted it, it has a syntax error and will not work (it has an errant ' inside the word "Saturday"). Otherwise, though, change the brackets ([ and ]) in your eval call to parentheses (( and )):
var obj = eval('('+msg.d+')');
However, it should almost never actually be necessary to do this (or indeed to use eval at all). It's almost always possible, and desirable, to refactor slightly and avoid it.
If that's a literal quote from your code, see also dvhh's answer below, your function argument name (msg.d) is invalid.
Using eval in this scenario is actual quite dangerous. You really ought to be using XML or JSON. (That's why they call it AJAX.)
the function argument should be a valid javascript identifier
try changing msg.d to msg_d for example
You may need to escape your string, because this example works fine:
function MyObject(myvar){
this.hello = function(){
alert('myvar= ' + myvar);
};
}
var obj1 = new MyObject('hello');
obj1.hello();
var obj2 = eval("new MyObject('world')");
obj2.hello();
(Edit: By the way, I assume msg.d is a typo due to editing the snipplet before posting on StackOverflow ?)
I would avoid using eval() for security reasons. If a user can get malicious code into the database, there's a chance it could end up in this eval expression, wreaking havoc for anybody who visits this page.
Instead of using eval, I'd recommending returning JSON from the AJAX request. You can then easily parse the values and build a new Person object with that data.

Categories