JSON.stringify - Strange behaviour with backslash in array - javascript

I was playing with JS while I noticed a strange behaviour with backslash \ inserted into a string within an array printed using JSON.stringify(). Of course the backslash is used to escaping special chars, but what happens if we need to put backslash in a string? Just use backslash to escape itself you're thinking, but it doesn't work with JSON.stringify
This should print one backslash
array = ['\\'];
document.write(JSON.stringify(array));
This should print two backslashes
array = ['\\\\'];
document.write(JSON.stringify(array));
Am I missing something? Could be that considered as a bug of JSON.stringify?

It is correct. JSON.stringify will return the required string to recreate that object - as your string requires that you escape a backslash, it will also return the required escape backslash to generate the string properly.
Try this:
array = ['\\'];
var x = JSON.stringify(array)
var y = JSON.parse(x)
if (array[0] == y[0]) alert("it works")
or
array = ['\\'];
if (JSON.parse(JSON.stringify(array))[0] == array[0]) alert("it really works")

Related

Why the .replace() and toUppercase() did not work in the second function? [duplicate]

I want to replace the smart quotes like ‘, ’, “ and ” to regular quotes. Also, I wanted to replace the ©, ® and ™. I used the following code. But it doesn't help.
Kindly help me to resolve this issue.
str.replace(/[“”]/g, '"');
str.replace(/[‘’]/g, "'");
Use:
str = str.replace(/[“”]/g, '"');
str = str.replace(/[‘’]/g, "'");
or to do it in one statement:
str = str.replace(/[“”]/g, '"').replace(/[‘’]/g,"'");
In JavaScript (as in many other languages) strings are immutable - string "replacement" methods actually just return the new string instead of modifying the string in place.
The MDN JavaScript reference entry for replace states:
Returns a new string with some or all matches of a pattern replaced by a replacement.
…
This method does not change the String object it is called on. It simply returns a new string.
replace return the resulting string
str = str.replace(/["']/, '');
The OP doesn't say why it isn't working, but there seems to be problems related to the encoding of the file. If I have an ANSI encoded file and I do:
var s = "“This is a test” ‘Another test’";
s = s.replace(/[“”]/g, '"').replace(/[‘’]/g,"'");
document.writeln(s);
I get:
"This is a test" "Another test"
I converted the encoding to UTF-8, fixed the smart quotes (which broke when I changed encoding), then converted back to ANSI and the problem went away.
Note that when I copied and pasted the double and single smart quotes off this page into my test document (ANSI encoded) and ran this code:
var s = "“This is a test” ‘Another test’";
for (var i = 0; i < s.length; i++) {
document.writeln(s.charAt(i) + '=' + s.charCodeAt(i));
}
I discovered that all the smart quotes showed up as ? = 63.
So, to the OP, determine where the smart quotes are originating and make sure they are the character codes you expect them to be. If they are not, consider changing the encoding of the source so they arrive as “ = 8220, ” = 8221, ‘ = 8216 and ’ = 8217. Use my loop to examine the source, if the smart quotes are showing up with any charCodeAt() values other than those I've listed, replace() will not work as written.
To replace all regular quotes with smart quotes, I am using a similar function. You must specify the CharCode as some different computers/browsers default settings may identify the plain characters differently ("",",',').
Using the CharCode with call the ASCII character, which will eliminate the room for error across different browsers, and operating systems. This is also helpful for bilingual use (accents, etc.).
To replace smart quotes with SINGLE QUOTES
function unSmartQuotify(n){
var name = n;
var apos = String.fromCharCode(39);
while (n.indexOf("'") > -1)
name = name.replace("'" , apos);
return name;
}
To find the other ASCII values you may need. Check here.

replace multiple words in string based on an array [duplicate]

I want to replace the smart quotes like ‘, ’, “ and ” to regular quotes. Also, I wanted to replace the ©, ® and ™. I used the following code. But it doesn't help.
Kindly help me to resolve this issue.
str.replace(/[“”]/g, '"');
str.replace(/[‘’]/g, "'");
Use:
str = str.replace(/[“”]/g, '"');
str = str.replace(/[‘’]/g, "'");
or to do it in one statement:
str = str.replace(/[“”]/g, '"').replace(/[‘’]/g,"'");
In JavaScript (as in many other languages) strings are immutable - string "replacement" methods actually just return the new string instead of modifying the string in place.
The MDN JavaScript reference entry for replace states:
Returns a new string with some or all matches of a pattern replaced by a replacement.
…
This method does not change the String object it is called on. It simply returns a new string.
replace return the resulting string
str = str.replace(/["']/, '');
The OP doesn't say why it isn't working, but there seems to be problems related to the encoding of the file. If I have an ANSI encoded file and I do:
var s = "“This is a test” ‘Another test’";
s = s.replace(/[“”]/g, '"').replace(/[‘’]/g,"'");
document.writeln(s);
I get:
"This is a test" "Another test"
I converted the encoding to UTF-8, fixed the smart quotes (which broke when I changed encoding), then converted back to ANSI and the problem went away.
Note that when I copied and pasted the double and single smart quotes off this page into my test document (ANSI encoded) and ran this code:
var s = "“This is a test” ‘Another test’";
for (var i = 0; i < s.length; i++) {
document.writeln(s.charAt(i) + '=' + s.charCodeAt(i));
}
I discovered that all the smart quotes showed up as ? = 63.
So, to the OP, determine where the smart quotes are originating and make sure they are the character codes you expect them to be. If they are not, consider changing the encoding of the source so they arrive as “ = 8220, ” = 8221, ‘ = 8216 and ’ = 8217. Use my loop to examine the source, if the smart quotes are showing up with any charCodeAt() values other than those I've listed, replace() will not work as written.
To replace all regular quotes with smart quotes, I am using a similar function. You must specify the CharCode as some different computers/browsers default settings may identify the plain characters differently ("",",',').
Using the CharCode with call the ASCII character, which will eliminate the room for error across different browsers, and operating systems. This is also helpful for bilingual use (accents, etc.).
To replace smart quotes with SINGLE QUOTES
function unSmartQuotify(n){
var name = n;
var apos = String.fromCharCode(39);
while (n.indexOf("'") > -1)
name = name.replace("'" , apos);
return name;
}
To find the other ASCII values you may need. Check here.

Escaping backslash in a string containing backslash

I have a string containing I\u2019m (with backslashes not escaped)
var myString = 'I\\u2019m'; // I\u2019m
But then I need a function that 'escape backslashes' that string, so the function I'm looking for would return I'm
backslashString(myString); // I'm
I've tried using eval:
function backslashString(input){
input = input.replace(/'/g, "\\'"); // Replace ' with \' that's going to mess up eval
return eval(`'${input}'`);
}
But is there a proper way of doing it? I'm looking for a function that escape backslashes a string containing I\u2019m to I'm and also handles if there's an extra backslash (A lost \ backslash)
EDIT:
I did not ask what I meant from the start. This not only applies to unicode characters, but applies to all backslash characters including \n
The backslashes aren’t the real problem here - the real problem is the difference between code and data.
\uXXXX is JavaScript syntax to write the Unicode codepoint of a character in a text literal. It gets replaced with the actual character, when the JavaScript parser interprets this code.
Now you have a variable that contains the value I\u2019m already - that is data. This does not get parsed as JavaScript, so it does mean the literal characters I\u2019m, and not I’m. eval can “fix” that, because the missing step of interpreting this as code is simply what eval does.
If you do not want to use eval (and thereby invite all the potential risks that entails, if the input data is not completely under your control), then you can parse those numeric values from the string using regular expressions, and then use String.formCharCode to create the actual Unicode character from the given code point:
var myString = 'I\\u2019m and I\\u2018m';
var myNewString = myString.replace(/\\u([0-9]+)/g, function(m, n) {
return String.fromCharCode(parseInt(n, 16)) }
);
console.log(myNewString)
/\\u([0-9]+)/g - regular expression to match this \uXXXX format (X=digits), g modifier to replace all matches instead of stopping after the first.
parseInt(n, 16) - to convert the hexadecimal value to a decimal first, because String.fromCharCode wants the latter.
decodeURIComponent(JSON.parse('"I\\u2019m"'));
OR for multiple
'I\\\u2019m'.split('\\').join().replace(/,/g,'');
'I\u2019m'.split('\\').join().replace(/,/g,'');
Looks like there's no other way other than eval (JSON.parse doesn't like new lines in strings)
NOTE: The function would return false if it has a trailing backslash
function backslashString(input){
input = input.replace(/`/g, '\\`'); // Escape quotes for input to eval
try{
return eval('`'+input+'`');
}catch(e){ // Will return false if input has errors in backslashing
return false;
}
}

Split string str.split("\\") using javascript

i have a string "demo1\demo2".
var str="demo1\demo2";
console.log(str.split("\\")[1])); \\gives undefined
console.log(str.split("\")[1])); \\gives undefined
gives undefined.
i need to demo2 in console.log
You're escaping the d after the \ in str. You need to escape the \ in str:
const str = 'demo1\\demo2';
console.log(str.split('\\'));
Just like #SimpleJ already answered, you need to escape your backslash so that it is not considered to be escaping the next character itself. As proof, when you don't escape your backslash with another backslash, here is how your string gets outputted (in case you haven't checked this yourself already):
> console.log('demo1\demo2')
demo1
undefined
> console.log('demo1\\demo2')
demo1\demo2
undefined
> console.log("demo1\demo2")
demo1
undefined
> console.log("demo1\\demo2") // same goes for double quoted strings
demo1\demo2
undefined
So this is the way to go:
"demo1\\demo2".split("\\")
If the items inside need escaping, you could run it through something like this first.
If you just need 'demo2' and you know what characters it has, you could something like:
console.log(str.match(/[^a-z0-9A-Z]([a-z0-9A-Z]*)$/)[1]);
or similar.

JSON.stringify escapes double quotes every time when stringified

I am storing JSON objects retreived from web service to objects in javascript. In many places this gets stringified(This obj goes through some plugins and it strigifies and stores it and retreives it) and it adds multiple slashes. How can I avoid it ?
http://jsfiddle.net/MJDYv/2/
var obj = {"a":"b", "c":["1", "2", "3"]};
var s = "";
console.log(obj);
s = JSON.stringify(obj);
alert(s); // Proper String
s = JSON.stringify(s);
alert(s); // Extra slash added, Quotes are escaped
s = JSON.stringify(s);
alert(s); // Again quotes escaped or slash escaped but one more slash gets added
var obj2 = JSON.parse(s);
console.log(obj2); // Still a String with one less slash, not a JSON object !
So when parsing this multiple string I end up with a string again. And when tried to access like an object it crashes.
I tried to remove slash by using replace(/\\/g,"") but I end with this : ""{"a":"b","c":["1","2","3"]}""
What did you expect to happen?
JSON.stringify does not act like an "identity" function when called on data that has already been converted to JSON. By design, it will escape quote marks, backslashes, etc.
You need to call JSON.parse() exactly as many times as you called JSON.stringify() to get back the same object you put in.
Try
JSON.stringify(s).replace(/\\"/g, '"')
You can avoid that simply by calling JSON.stringify() exactly once on the data you want turn into JSON.
Try this:
s = {"a":"b", "c":["1", "2", "3"]}
JSON.stringify(JSON.stringify(s))
gives the output as
'"{\"a\":\"b\",\"c\":[\"1\",\"2\",\"3\"]}"'

Categories

Resources