Access escaped properties of an object in javascript - javascript

I have an object with a property like this:
var RouteMetaSet = {
'\/user-management\/users': {
path: '/user-management/users',
name: 'User Management',
iconClassList: ['fa', 'fa-user'],
}
};
I can easily get the value of the property like this:
console.log(RouteMetaSet['\/user-management\/users'])
However, if I assign the key to a variable and then push it inside the brackets, it's impossible.
var originialString = /user-management/users;
var escapedString = originialString.replace(/[-/<>*()?]/g, "\\$&"); // it should be "\/user-management\/users"
console.log(RouteMetaSet[escapedString]); // undefined
Am I wrong somewhere on this point?

First. This:
var originialString = /user-management/users;
… is just syntax errors.
String literals in JS must be quoted.
Next:
Escape characters have meaning in JavaScript source code.
When the string literal is parsed by the JavaScript engine it is turned into the string. During this process, the escape characters are consumed.
They aren't part of the data at all. If you insert slashes with regular expressions, then you are just inserting slashes (not escape sequences) into the string.
var RouteMetaSet = {
'\/user-management\/users': {
path: '/user-management/users',
name: 'User Management',
iconClassList: ['fa', 'fa-user'],
}
};
var originialString = "/user-management/users";
console.log(RouteMetaSet[originialString]);
Aside: the / character does not need to be escaped in a JS string literal unless it forms part of the sequence </script> inside an inline script.
Generated code often escapes all / characters as a simple and effective way to avoid that problem.
If the property name included characters that did need to be escaped (such as a \) then, by the time the string had been parsed, it would be too late to sensibly do anything about it.
var originalString = "Example\t";
Is that supposed to be a tab or is it supposed to be a \ followed by a t?
If you can't trust the code to be right in the first place, you have a problem.

Related

Best practice for converting string to object in JavaScript

I am working on a small UI for JSON editing which includes some object and string manipulation. I was able to make it work, but one of the fields is bit tricky and I would be grateful for an advice.
Initial string:
'localhost=3000,password=12345,ssl=True,isAdmin=False'
Should be converted to this:
{ app_server: 'localhost:3000', app_password:'12345', app_ssl: 'True', app_isAdmin: 'False' }
I was able to do that by first splitting the string with the ',' which returns an array. And then I would loop through the second array and split by '='. In the last step I would simply use forEach to loop through the array and create an object:
const obj = {}
arr2.forEach((item) => (obj[`app_${item[0]}`] = item[1]));
This approach works, but in case some of the fields, i.e password contains ',' or '=', my code will break. Any idea on how to approach this? Would some advanced regex be a good idea?
Edit: In order to make things simple, it seems that I have caused an opposite effect, so I apologize for that.
The mentioned string is a part of larger JSON file, it is the one of the values. On the high level, I am changing the shape of the object, every value that has the structure I described 'server='something, password=1234, ssl=True', has to be transformed into separate values which will populate the input fields. After that, user modify them or simply download the file (I have separate logic for joining the input fields into the initial shape again)
Observation/Limitation with the design that you have :
As per your comment, none of the special characters is escaped in any way then how we will read this string password=12345,ssl=True ? It will be app_password: 12345,ssl=True or app_password: 12345 ?
why localhost=3000 is converted into app_server: 'localhost:3000' instead of app_localhost: '3000' like other keys ? Is there any special requirement for this ?
You have to design your password field in the way that it will not accept at least , character which is basically used to split the string.
Here you go, If we can correct the above mentioned design observations :
const str = 'localhost=3000,password=123=45,ssl=True,isAdmin=False';
const splittedStr = str.split(',');
const result = {};
splittedStr.forEach(s => {
const [key, ...values] = s.split('=')
const value = values.join('=');
result[`app_${key}`] = value
});
console.log(result);
As you can see in above code snippet, I added password value as 123=45 and it is working properly as per the requirement.
You can use a regular expression that matches key and value in the key=value format, and will capture anything between single quotes when the value happens to start with a single quote:
(\w+)=(?:'((?:\\.|[^'])*)'|([^,]+))
This assumes that:
The key consists of alphanumerical characters and underscores only
There is no white space around the = (any space that follows it, is considered part of the value)
If the value starts with a single quote, it is considered a delimiter for the whole value, which will be terminated by another quote that must be followed by a comma, or must be the last character in the string.
If the value is not quoted, all characters up to the next comma or end of the string will be part of the value.
As you've explained that the first part does not follow the key=value pattern, but is just a value, we need to deal with this exception. I suggest prefixing the string with server=, so that now also that first part has the key=value pattern.
Furthermore, as this input is part of a value that occurs in JSON, it should be parsed as a JSON string (double quoted), in order to decode any escaped characters that might occur in it, like for instance \n (backslash followed by "n").
Since it was not clarified how quotes would be escaped when they occur in a quoted string, it remains undecided how for instance a password (or any text field) can include a quote. The above regex will require that if there is a character after a quote that is not a comma, the quote will be considered part of the value, as opposed to terminating the string. But this is just shifting the problem, as now it is impossible to encode the sequence ', in a quoted field. If ever this point is clarified, the regex can be adapted accordingly.
Implementation in JavaScript:
const regex = /(\w+)=(?:'(.*?)'(?![^,])|([^,]+))/g;
function parse(s) {
return Object.fromEntries(Array.from(JSON.parse('"server=' + s + '"').matchAll(regex),
([_, key, quoted, value]) => ["app_" + key, quoted ?? (isNaN(value) ? value : +value)]
));
}
// demo:
// Password includes here a single quote and a JSON encoded newline character
const s = "localhost:3000, password='12'\\n345', ssl='True', isAdmin='False'";
console.log(parse(s));

How to filter a string containing round brackets (or parenthesis) while using jsonpath?

js code is ....
var queryString = 'Dolphin Travels (Sagar Travels)';
var results = jsonPath(jsonvar, "$.availableTrips[?("+queryString+")]");
Error :
SyntaxError: jsonPath: unterminated string literal: _v.travels == 'Dolphin Travels (Sagar Travels)
First, let's get some prerequisites figured out:
You are searching 'Dolphin Travels (Sagar Travels)', but I don't see this in your test data (at least that you've shown), so I can't really tell what part of the object/array it is in (whether it is a value or a key).
Here is the sample data I'm working with:
var t = {
'availableTrips': [
{
'busType': 'Volvo A/C-Multi Axle Semi sleeper (2+2)',
'busTypeId': '101',
'fares': 250,
'travels': 'SVR Tours and Travel [Citizen]'
},
{
'busType': 'Lorem Ipsum',
'busTypeId': '102',
'fares': 300,
'travels': 'SVR Tours and Travel [Citizen]'
}
]
}
Simple usage of jsonPath (I'm also assuming you mean this jsonPath library, since you did not specify):
jsonPath(t,'$.availableTrips[?(/SVR/.test(#.travels))]');
Yields the array of objects in the availableTrips array since the string SVR (as a regex) is in both of them.
jsonPath(t,'$.availableTrips[?(/Volvo/.test(#.busType))]');
Yields only the first item in the availableTrips array, equivalent to t.availableTrips[0].
Now, to answer your question:
When escaping, you can use a backslash \, but since you are in a string that is interpreted, you'll need to escape it TWICE: \\. Once for the string being sent as a parameter for jsonParse and again as part of the expression being interpreted within jsonParse. Like so:
jsonPath(t,'$.availableTrips[?(/\\(2\\+2\\)/.test(#.busType))]');
Notice that I also had to escape the + quantifier, as well as the ( and ) group metacharacters.
In terms of sanitizing user input, e.g. var queryString = 'Dolphin Travels (Sagar Travels)';, you can perform the following (see What special characters must be escaped in regular expressions?):
var sanitizedQueryString = queryString.replace(/([\.\^\$\*\+\?\(\)\[\{\\\|])/g,'\\$1');

javascript regex to require at least one special character

I've seen plenty of regex examples that will not allow any special characters. I need one that requires at least one special character.
I'm looking at a C# regex
var regexItem = new Regex("^[a-zA-Z0-9 ]*$");
Can this be converted to use with javascript? Do I need to escape any of the characters?
Based an example I have built this so far:
var regex = "^[a-zA-Z0-9 ]*$";
//Must have one special character
if (regex.exec(resetPassword)) {
isValid = false;
$('#vsResetPassword').append('Password must contain at least 1 special character.');
}
Can someone please identify my error, or guide me down a more efficient path? The error I'm currently getting is that regex has no 'exec' method
Your problem is that "^[a-zA-Z0-9 ]*$" is a string, and you need a regex:
var regex = /^[a-zA-Z0-9 ]*$/; // one way
var regex = new RegExp("^[a-zA-Z0-9 ]*$"); // another way
[more information]
Other than that, your code looks fine.
In javascript, regexs are formatted like this:
/^[a-zA-Z0-9 ]*$/
Note that there are no quotation marks and instead you use forward slashes at the beginning and end.
In javascript, you can create a regular expression object two ways.
1) You can use the constructor method with the RegExp object (note the different spelling than what you were using):
var regexItem = new RegExp("^[a-zA-Z0-9 ]*$");
2) You can use the literal syntax built into the language:
var regexItem = /^[a-zA-Z0-9 ]*$/;
The advantage of the second is that you only have to escape a forward slash, you don't have to worry about quotes. The advantage of the first is that you can programmatically construct a string from various parts and then pass it to the RegExp constructor.
Further, the optional flags for the regular expression are passed like this in the two forms:
var regexItem = new RegExp("^[A-Z0-9 ]*$", "i");
var regexItem = /^[A-Z0-9 ]*$/i;
In javascript, it seems to be a more common convention to the user /regex/ method that is built into the parser unless you are dynamically constructing a string or the flags.

string.Format did not work for string line type parameter?

I have to pass two parameters to CallSome()
string.Format("CallSome({0},'{1}');", someId, someName);
But someName did not work for this kind of values which is having space. like
Its working for '123', 'name'
But not for this 'My Name' Its given an error of this After 'My
Try this
string.Format("CallSome({0},''{1}'');", someId, someName);
You need to escape single quote by putting extra single quote in start and end.
Assuming you are using C# and you want to output this to a web response in ASP.NET or similar web technology, then... your code should work.
For example, given someId = 123 and someName = "word, word":
CallSome(123,'word, word');
Just, check the output code you are getting in the web page, it will reveal the truth.
Unless it is being inserted in a place where it is surrounded by single quotes.
For example, given someId = 123 and someName = "word, word":
var something = 'CallSome(123, 'word, word')';
So, the first single quotes looks like the end of the text as far as the browser is concerned. In that case, you should use double quotes, like this:
var something = "CallSome(123, 'word, word')";
or this:
var something = 'CallSome(123, "word, word")';
Alternatively, you can escape your single quotes:
var something = 'CallSome(123, \'word, word\')';
Unless it has quotes in the argument.
For example, given someId = 123 and someName = "word' word":
var something = 'CallSome(123, 'word' word')';
Again, the first single quotes looks like the end of the text as far as the browser is concerned. That case is a bit more complicated, because it requires to escape quotes one way:
var something = "CallSome(123, 'word\' word')";
Or another:
var something = 'CallSome(123, "word\' word")';
Unless it has a new line, a javascript comment, or I don't know what else in the argument.
Just don't have those!
Now, in C# you Need to escape your quotes. To output double quotes you can do this:
string.Format("CallSome({0},\"{1}\");", someId, someName);
That gives:
CallSome(123,"word, word");
On the other hand, if you really need to use single quotes (I don't think so, given the bug), then you will have to escape them in the output javascript:
string.Format("CallSome({0},\\'{1}\\');", someId, someName);
That gives:
CallSome(123, \'word, word\');
Which is ok in if it is part of a quoted string, as my examples above:
var something = 'CallSome(123, \'word, word\')';

Javascript match last #<User>

I'm trying to make an auto-complete function for twitter usernames.
So far, I have the following code:
function OnKeyUp(txtboxid){
var text = $('#'+txtboxid).val()
var regex = '(^|\s)#(\w*[a-zA-Z_]+\w*)'
var results = text.match(RegExp(regex, 'gm'))
console.debug(results)
}
The problem is, it matches only text when it is at the beginning of the string (eg: #yser)
What i want is a regex that can mach such a string like this "hello #user2 , #user and #user3 how are you"
I'm not sure how to accomplish this.
Searched google for about 3 hours now and still nothing found.
Also, it would be great to only the the last username when its changed.
Your regex is fine. The only problem is that backslashes in the string will be removed or replaced when the string is parsed, instead of being interpreted by the regular expression parser. You need to re-escape each of them with an extra backslash:
var regex = '(^|\\s)#(\\w*[a-zA-Z_]+\\w*)';
Instead of specifying the regular expression with a string and the RegEx function, you should usually use a regular expression literal. It's delimited by backslashes instead of double-quotes, with the flags appended to the end:
var results = text.match(/(^|\s)#(\w*[a-zA-Z_]+\w*)/gm);

Categories