Specific replacement of quotes in a string object - javascript

I've an object as a string, like this :
{'fze': 'ffefe', 'zfe': 'grg', 'fefe': 'gggv', "c'est": 'aaze', "it's": "jack's time", 'hey': 'now'}
I'd like to replace all single quote to double quote, but not the one that is inside the double quote (for example, the words : "c'est", "it's" and "jack's time", because they already have a single quote inside)
The final result would be this :
{"fze": "ffefe", "zfe": "grg", "fefe": "gggv", "c'est": "aaze", "it's": "jack's time", "hey": "now"}
I already tried with replaceAll, but I need more conditions for that.
Do you have an ideas on how to solve this?

Provided your input is really a string, a combination of eval + JSON.stringify should do the trick:
your_string = `{'fze': 'ffefe', 'zfe': 'grg', 'fefe': 'gggv', "c'est": 'aaze', "it's": "jack's time", 'hey': 'now'}`
console.log(JSON.stringify(eval('0,' + your_string)))
As usual with eval, never use it with untrusted input.
The 0, part is necessary to turn the input into an expression, otherwise eval would treat it as a code block (and fail).

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));

String replace with with unescaped curly brace in JSON

I'm trying to replace a value in a string with a double curly (used by postman for variable substitution), but every time I try to quote or escape the braces, I always get additional escaped quotes or double escaped braces, all of which break the substitution:
Original String:
"header": [{"key": "x-device-auth","value": "\"token\""}]
OriginalString.replace('token','{{token}}')
Result:
"header":[{"key":"x-device-auth","value":"\"{{token}}\""}]
If I search for .replace('\"token\"','{{token}}'), I don't get a match. The final string needs to be:
"header": [{"key": "x-device-auth","value": "{{token}}"}]
You should be looking for token with the escaped wrapping double quotes, since you also want to replace those.
var originalString = '"header": [{"key": "x-device-auth","value": "\\"token\\""}]';
console.log(originalString);
console.log(originalString.replace('\\"token\\"','{{token}}'));
originalString = '"header": [{"key": "x-device-auth","value": "\"token\""}]';
console.log(originalString);
console.log(originalString.replace('"token"','{{token}}'));
I have added two cases, one with the original string actually containing backslashes (first originalstring definition). The second without. Choose the one, that best matches your actual input :-)
I dont see the input string is having proper escape characters applied. As you posted question in javascript tag, I tried below with javascript and its giving required results.
var str = "\"header\": [[{\"key\": \"x-device-auth\",\"value\": \"token\"}]";
var res = str.replace('token','{{token}}');

Split string by "\" Node.js

Hy everyone, I'm having some issues with split a string because when I log her value seems ok but in the final result appears "\" like,
"map":"{\"isRoot\": true, \"visible\": true}" instead of have "map":"{"isRoot": true, "visible": true}"
So I have this code
if(mapData!=undefined){
var map = mapData.map;
console.log("sendDeviceInfo getServicesMapInfoById map >>>>>>>>>>>>>>>>>>>>> ", map);
sendData.map=map;
createLog('debug', __dirname, __filename.slice(__dirname.length + 1, -3), device.id, 'sendDeviceInfo','sendData.map 1', sendData.map);
}
And my logs:
sendDeviceInfo getServicesMapInfoById map >>>>>>>>>>>>>>>>>>>>> {"isRoot": true, "visible": true}
4|wscontro | [2017-05-30 12:36:03.010] - debug: /opt/wscontroller/wscontroller-service/scripts/gps GpsController 58a8c61b-f11d-4874-91df-3a5205e4145f sendDeviceInfo sendData.map 1 "{\"isRoot\": true, \"visible\": true}"
Why is this happening?
--- solution
if(mapData!=undefined){
var map = mapData.map;
var aux = map.split('\\').join('');
var jsonObject = JSON.parse(aux);
sendData.map = jsonObject;
}
You can replace them like this
yourJsonString = yourJsonString.split('\\').join('');
var jsonObject = JSON.parse(yourJsonString);
That's nothing to worry about. That "\"s don't actually exist in the string.
When you use JSON.stringify in node.js, the result always has "\"s to escape special characters, and double quotes are special characters. That character is the unix escape character. That's why it appears kind of everywhere.
Try using below code to remove the escape sequence
mapData = mapData.replace(/\\"/g, '"');
Your Json string is using "-marks.
Since Json is a string itself, we need a solution to tell the compiler which "-marks are marking the string, and which "-marks are part of the string itself.
To do this it's very common among languages to use the -character, and by typing for instance \", you're 'escaping' the "-mark.
Imagine a string like this: He said to me: "Hi there". Now if we want to make this into a string we could try "He said to me: "Hi there".", though the compiler will see 2 strings and a lost period, because it does not distinguish between the start and end of the string, and the "-marks that are part of the content itself.
When you console.log() an actual string, it will not show the "-marks that show the start and end of the string, because it is not necessary. Because of that, there is no need to escape the "-marks in the string itself.
Whatever the createLog() function does, it apparently needs to note the string down as it being an actual string, and therefor it needs to escape the "-marks with a '\' sign.

String variable is not accepting "?" sign

I made code with:
element(by.className('charge')).getText()
.then(function(text){
var blabla = "Is this my string?";
expect(text.match(blabla)).toBe(true);
console.log(text);
});
And even is output of my console equal to my blabla variable,
I'm getting result:
Expected [ 'Is this my string' ] to be true.
without any "?" sign.
How is it possible?
The argument for match is:
A regular expression object. If a non-RegExp object obj is passed, it is implicitly converted to a RegExp by using new RegExp(obj).
So don't pass it a string. Explicitly pass it a regular expression object (since that involves much less pain that converting strings in to regex and having to deal with two levels of syntax to escape through).
Regular expressions treat ? as a special character (in the context of your code it means "The g should appear 0 or 1 time". You need to escape question marks if you want to match them.
var blabla = /Is this my string\?/;
That said, if you want to match the whole string, it would be easier to just make that the test:
var blabla = "Is this my string?";
expect(text).toBe(blabla);
The argument to match is meant to be a regular expression where ? has a special meaning. You probably meant toEqual() instead:
expect(element(by.className('charge')).getText()).toEqual("Is this my string?");
If you want a regular expression match, make a regular expression object and use toMatch():
var blabla = /Is this my string\?/;
expect(element(by.className('charge')).getText()).toMatch(blabla);
Note that in protractor expect() is "patched" to resolve promises implicitly and you don't need to use then().
You probably misundertood what match method does in JS strings:
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/String/match
It will basically use the regex to return the groups that match, so, in this case
< ("Is this my string").match("Is this my string?");
> ["Is this my string"]
The answer is correct. What you want to do is simply compare the strings, just do:
< "Is this my string" === "Is this my string?";
> false
Note it has nothing to do with the test engine you are using (that I do not know), but there propably is a better way to do it than
expect(text === blabla).toBe(true);
Something
expect(text, blabla).toBeEqual();
So the error message is pretty ;)
The string argument provided to match() is a regular expression and the ? in this context means "match the previous zero or one times". Which it does in your example :-)
You can explicitly escape the question make by writing \?, in which case the behavior will be as you expect.
Cheers,

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');

Categories