JSP attribute JSON object is dropping escape characters in Javascript - javascript

I have a server-side controller which is adding an attribute which is a Java object converted to JSON using Jackson:
ObjectMapper mapper = new ObjectMapper();
model.addAttribute("commentObj", mapper.writeValueAsString(commentObject);
My commentObject has a field "comments" which contains quotation marks (") that JSON needs to escape. When I do a simple print-out from the JSP of the commentObject, everything looks good:
[{"commentId":123,"comments": "this \"test\" is here"}]
As you see, the quotes get escaped properly (\").
My problem comes with the javascript on this page that also needs to access this object. So when I run the following:
<script>
var test = ${commentObj};
</script>
If I take a look at the 'test' var, the comments field now reads as follows:
"this "test" is here"
vs.
"this \"test\" is here"
This causes a problem because JSON.parse() will throw an error on 'test' because it is not properly formed JSON anymore.
So my question is, how do I manage to get my commentObj into a javascript object while keeping the escape characters so that I can JSON.parse it properly?

Sorry, written at the end of a long day while sick and only just realized now that the 'test' var ends up being a fully formed JS object. So I am able to use that.
That said, I still have the question of how that is happening? It seems to me that it should be coming in as a JSON string that I need to call JSON.parse on. Anyone have an explanation?

Related

Angular Markdown Parsing "\n" Newline Characters Issue

I've created a blog where markdown is returned as a string from my backend, however when I return a string with the correct newline characters it does not behave as expected.
I am using ngx-markdown to handle parsing of markdown characters, and using the ngPreserveWhitespaces attribute to ensure this should be functioning as expected.
Example:
// Example #1 Returned String
"## This is a subheader\n This is a sentence"
// Output
<h2>This is a subheader\n This is a sentence</h2>
It displays it as a single line with the newline character physically rendered as text, as above.
However within any of my Angular components I can literally write this same string as a property on the component and return it, and it renders correctly like so:
// Example #2 Hard Coded String
public correct: string = "## This is a subheader\n This is a sentence";
// Output
<h2>This is a subheader</h2>
<p>This is a sentence</p>
As mentioned, the markdown parser I am using is implemented as such:
<markdown ngPreserveWhitespaces>{{content}}</markdown>
I have also attempted to do this by setting ngPreserveWhitespaces within the main/tsconfig files. However I do not believe this is what the issue is, as I can (natively in JS) console.log both my returned string (#1) and the hard coded string (#2) and even my damn logs display differently (with the latter formatting correctly and the former just stringifying the output).
I have attempted:
JSON stringify/parsing the data in multiple ways (as well as without)
I have attempted using regex to manually replace characters
I have attempted to just manually use <br />
I have tried everything outlined here regarding this markdown parser handling whitespace (which I do not believe is the issue)
Nothing appears to appease the newline gods.
Solution
Okay so I've found my solution to this, I am now storing my markdown string as such:
"## This is a subheader\n This is a sentence"
This difference here is the interface I'm storing this within (a Mongo db) puts the speechmarks around string values already, so it now actually looks like this:
""## This is a subheader\n This is a sentence""
Which is more a weird thing with MongoDB Compass than with what I was attempting.
From this, I am able to JSON.parse the value correctly (previously it was attempting to do so with a string that wasn't valid JSON as it wasn't enclosed in double speechmarks).
I am now handling this in an extension of a Property class I have for each of these called HtmlProperty which when instantiated, parses the value correctly.

How to assign large string to a variable without ILLEGAL Token error?

I need to assign a long string (4 pages worth of text) to a variable, so far I've been doing it like this
var myText = "[SOME] Text goes \
.. here ? and 'there' \
is more ( to \
come etc. !)";
slashes at the end need to be added to all of the text, and I can't imagine how long this will take to do manually. Also, I get ILLEGAL error for some reason I don't understand for the first line.
Therefore I wanted to find out the best way to handle this situation. I was looking into solutions of passing in a .txt file, but would rather do it as a really long string (this is not a production app). Also string shown in example is random, showing that there can be a lot of various characters in it that need to be accounted for.
You have to concatenate the string:
var t = ""
+"text line 1"
...
+"text line n"
But I would put the text in a text file and read it using xhr (on client) or io (on server).
You cannot have a multiline string definition in javascript but you have several options :
save your text in a file and read this file from your program
use the multiline npm module which propose a hack to use function comments as multiline string definitions
use ES6 multi-line template strings notation, which have multi-line support - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/template_strings#Multi-line_strings
saving the text in a file would seem to me as the preferred option in your case since the text seem to be very long an potentially coming from an untrusted source. You do not want the pasted text to close the string and start doing innapropriate function calls.

Error Parsing JSON with escaped quotes

I am getting the following json object when I call the URL from Browser which I expect no data in it.
"{\"data\":[], \"SkipToken\":\"\", \"top\":\"\"}"
However, when I tried to call it in javascript it gives me error Parsing Json message
dspservice.callService(URL, "GET", "", function (data) {
var dataList = JSON.parse(data);
)};
This code was working before I have no idea why all of a sudden stopped working and throwing me error.
You say the server is returning the JSON (omitting the enclosing quotes):
{\"data\":[], \"SkipToken\":\"\", \"top\":\"\"}
This is invalid JSON. The quote marks in JSON surrounding strings and property names should not be preceded by a backslash. The backslash in JSON is strictly for inserting double quote marks inside a string. (It can also be used to escape other characters inside strings, but that is not relevant here.)
Correct JSON would be:
{"data":[], "SkipToken":"", "top":""}
If your server returned this, it would parse correctly.
The confusion here, and the reports by other posters that it seems like your string should work, lies in the fact that in a simple-minded test, where I type this string into the console:
var x = "{\"data\":[], \"SkipToken\":\"\", \"top\":\"\"}";
the JavaScript string literal escaping mechanism, which is entirely distinct from the use of escapes in JSON, results in a string with the value
{"data":[], "SkipToken":"", "top":""}
which of course JSON.parse can handle just fine. But Javascript string escaping applies to string literals in source code, not to things coming down from the server.
To fix the server's incorrectly-escaped JSON, you have two possibilities. One is to tell the server guys they don't need to (and must not) put backslashes before quote marks (except for quote marks inside strings). Then everything will work.
The other approach is to undo the escaping yourself before handing it off to JSON.parse. A first cut at this would be a simple regexp such as
data.replace(/\\"/g, '"')
as in
var dataList = JSON.parse(data.replace(/\\"/g, '"')
It might need additional tweaking depending on how the server guys are escaping quotes inside strings; are they sending \"\\"\", or possibly \"\\\"\"?
I cannot explain why this code that was working suddenly stopped working. My best guess is a change on the server side that started escaping the double quotes.
Since there is nothing wrong with the JSON string you gave us, the only other explanation is that the data being passed to your function is something other than what you listed.
To test this hypothesis, run the following code:
dspservice.callService(URL, "GET", "", handler(data));
function handler(data) {
var goodData = "{\"data\":[], \"SkipToken\":\"\", \"top\":\"\"}";
alert(goodData); // display the correct JSON string
var goodDataList = JSON.parse(goodData); // parse good string (should work)
alert(data); // display string in question
var dataList = JSON.parse(data); // try to parse it (should fail)
}
If the goodData JSON string can be parsed with no issues, and data appears to be incorrectly-formatted, then you have the answer to your question.
Place a breakpoint on the first line of the handler function, where goodData is defined. Then step through the code. From what you told me in your comments, it is still crashing during a JSON parse, but I'm willing to wager that it is failing on the second parse and not the first.
Did you mean that your JSON is like this?
"{\"data\":[], \"SkipToken\":\"\", \"top\":\"\"}"
Then data in your callback would be like this:
'"{\"data\":[], \"SkipToken\":\"\", \"top\":\"\"}"'
Because data is the fetched text content string.
You don't have to add extra quotes in your JSON:
{"data":[], "SkipToken":"", "top":""}

Parsing malformed JSON in JavaScript

Thanks for looking!
BACKGROUND
I am writing some front-end code that consumes a JSON service which is returning malformed JSON. Specifically, the keys are not surrounded with quotes:
{foo: "bar"}
I have NO CONTROL over the service, so I am correcting this like so:
var scrubbedJson = dirtyJson.replace(/(['"])?([a-zA-Z0-9_]+)(['"])?:/g, '"$2": ');
This gives me well formed JSON:
{"foo": "bar"}
Problem
However, when I call JSON.parse(scrubbedJson), I still get an error. I suspect it may be because the entire JSON string is surrounded in double quotes but I am not sure.
UPDATE
This has been solved--the above code works fine. I had a rogue single quote in the body of the JSON that was returned. I got that out of there and everything now parses. Thanks.
Any help would be appreciated.
You can avoid using a regexp altogether and still output a JavaScript object from a malformed JSON string (keys without quotes, single quotes, etc), using this simple trick:
var jsonify = (function(div){
return function(json){
div.setAttribute('onclick', 'this.__json__ = ' + json);
div.click();
return div.__json__;
}
})(document.createElement('div'));
// Let's say you had a string like '{ one: 1 }' (malformed, a key without quotes)
// jsonify('{ one: 1 }') will output a good ol' JS object ;)
Here's a demo: http://codepen.io/csuwldcat/pen/dfzsu (open your console)
something like this may help to repair the json ..
$str='{foo:"bar"}';
echo preg_replace('/({)([a-zA-Z0-9]+)(:)/','$1"$2"${3}',$str);
Output:
{"foo":"bar"}
EDIT:
var str='{foo:"bar"}';
str.replace(/({)([a-zA-Z0-9]+)(:)/,'$1"$2"$3')
There is a project that takes care of all kinds of invalid cases in JSON https://github.com/freethenation/durable-json-lint
I was trying to solve the same problem using a regEx in Javascript. I have an app written for Node.js to parse incoming JSON, but wanted a "relaxed" version of the parser (see following comments), since it is inconvenient to put quotes around every key (name). Here is my solution:
var objKeysRegex = /({|,)(?:\s*)(?:')?([A-Za-z_$\.][A-Za-z0-9_ \-\.$]*)(?:')?(?:\s*):/g;// look for object names
var newQuotedKeysString = originalString.replace(objKeysRegex, "$1\"$2\":");// all object names should be double quoted
var newObject = JSON.parse(newQuotedKeysString);
Here's a breakdown of the regEx:
({|,) looks for the beginning of the object, a { for flat objects or , for embedded objects.
(?:\s*) finds but does not remember white space
(?:')? finds but does not remember a single quote (to be replaced by a double quote later). There will be either zero or one of these.
([A-Za-z_$\.][A-Za-z0-9_ \-\.$]*) is the name (or key). Starts with any letter, underscore, $, or dot, followed by zero or more alpha-numeric characters or underscores or dashes or dots or $.
the last character : is what delimits the name of the object from the value.
Now we can use replace() with some dressing to get our newly quoted keys:
originalString.replace(objKeysRegex, "$1\"$2\":")
where the $1 is either { or , depending on whether the object was embedded in another object. \" adds a double quote. $2 is the name. \" another double quote. and finally : finishes it off.
Test it out with
{keyOne: "value1", $keyTwo: "value 2", key-3:{key4:18.34}}
output:
{"keyOne": "value1","$keyTwo": "value 2","key-3":{"key4":18.34}}
Some comments:
I have not tested this method for speed, but from what I gather by reading some of these entries is that using a regex is faster than eval()
For my application, I'm limiting the characters that names are allowed to have with ([A-Za-z_$\.][A-Za-z0-9_ \-\.$]*) for my 'relaxed' version JSON parser. If you wanted to allow more characters in names (you can do that and still be valid), you could instead use ([^'":]+) to mean anything other than double or single quotes or a colon. You can have all sorts of stuff in here with this expression, so be careful.
One shortcoming is that this method actually changes the original incoming data (but I think that's what you wanted?). You could program around that to mitigate this issue - depends on your needs and resources available.
Hope this helps.
-John L.
How about?
function fixJson(json) {
var tempString, tempJson, output;
tempString = JSON.stringify(json);
tempJson = JSON.parse(tempString);
output = JSON.stringify(tempJson);
return output;
}

String with quotation marks from SpringMVC controller, not shown with javascript-jquery

I try to show data with jquery, sent from a controller of Spring MVC. The problem is the string have quotation marks from database, therefore, my code with javascript - jquery, not working.
For example, my string is (principal:"Carl Duvierts") in database, sending by the controller.
alert("${person.name}"); //not working
If the object you're using is already a string, you don't need the quotes around it in an alert.
//this will work
var stringWithQuotes = 'abc"de"fg';
alert(stringWithQuotes);//no quotation marks inside the parentheses
//The code you provided:
alert("${person.name}");
//will just alert the actual string '${person.name}', not what is referenced by the variable

Categories

Resources