JSON.parse and JSON.stringify error on special character in string - javascript

console.log(JSON.stringify($('.btn').attr('data-obj')))
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="btn btn-info user_action" data-action="edit_faqs" data-obj="{SysID:2,Artist:Json Mras,Song:I'm yours}" data-toggle="modal " data-target="#SongsModal
"><i class="fa fa-edit "></i> Edit</button>
I found this but this is a little different in my case.
When I tried using JSON.stringify on the data I can see in the dev tools
//I want I'm Yours
"{\"Song\":\"I"
The data is stored in my database and I get it in ajax request and I want to use JSON.stringify to it because I will put it as a data-* on a button which will then be used when I click the button. On button click I want to use JSON.parse so I can iterate over it.
How to escape all special characters in JSON.stringify and JSON.parse
Error is:
Uncaught SyntaxError: Unexpected end of JSON input
That points to the JSON.stringify
Added a snippet but it didnt recreate problem so I added an image
Database:
Update:
I get the data from ajax request. After getting the data I use data_array = JSON.stringify(data[i]); then apply the data as data-obj='" + data_array + "'

That's not a problem with JSON, it's a problem with your misuse of HTML.
You inserted a raw string into a HTML attribute, probably from a template, possibly by doing something like
<button data-obj="<?php echo json_encode($data); ?>">
Or possibly in JavaScript
container.innerHTML = '<button data-obj="' + JSON.stringify(data) + '">';
so your quotes end up clashing with HTML's. You need to change your quotes into HTML entities; the minimum is changing double quotes " into " if you are using double quotes around the HTML attribute (the most common scenario).
You have not told us how you insert the content into the HTML, so I can't tell you how to do it until you do clarify.
EDIT: Apparently you are building HTML in JavaScript by concatenation. In that case, the solution I showed would work:
container.innerHTML = '<button data-obj="' + data_array.replace(/"/g, '"') + '">';
Or, if you're using single quotes to enclose the attribute (not commonly done, but certainly an option), you would need to change those to &apos; instead:
container.innerHTML = "<button data-obj='" + data_array.replace(/'/g, '&apos;') + "'>";
However, given that it's JavaScript we're talking about, and it can work with DOM, and DOM knows what's what... there's many other solutions. The most primitive one is to work with DOM directly:
let button = document.createElement('button');
button.setAttribute('data-obj', data_array);
container.appendChild(button);
When you do this, JavaScript manipulates the DOM directly, not HTML, so escaping is not needed.
A level above this would be to use a library like jQuery:
$('<button>').data('obj', data_array).appendTo('#container');
A level yet above that would be to use a library that employs data binding, like Angular, React, Vue, Ractive... where you would just set the value on your model, and the document automagically reflects that change.
Changing manually " into " is only needed if you directly manipulate HTML.

Related

Adding JavaScript Function with arguments to an element from code behind

Hi Guys I've been dealing with an estrange thing while trying to pass string parameters to a JavaScript function from code behind, this is what I have actually in code behind which is wrong:
thumbnail = "<a href = 'javascript:RemovePirctureDetail(" + field1 + ",'" + tempname + "');' class='label label-default' rel='tooltip'>Remove</a>";
So this is the bad result I'm getting in the browser:
Remove
Meas that for some reason when I try to pass the string parameter, the html comes out bad formatted. The result should looks like this:
Remove
I tried already send the quotation marks like this /' from code behind, it did not work neither. How can I achieve this?
Thanks.
string thumbnail = "Remove";`
You need to use \ to escape the quotes inside, not /..
With javascript attribute I wouldn't use single quote, because it could be messy
Try to change in this way:
thumbnail = "Remove";
PS: Actually, I would NEVER use single quotes with attributes, it will cause an HTML validation error, HTML is not well formed with single quotes for attributes (although with inspection tools you see double quotes.. because inspection tools have the need to work with a well formed HTML, so if you want to see the real HTML of your page, view the source code (generally the option is on right-click on the page)

How to mark certain parts of string to be read as code in JavaScript

I am working on ASP.NET Web Forms application. A lot of my information is stored in XML files on the server side. Via Ajax calls I retrieve some of that data for use in the front end.
The problem is that sometimes I have to write in the XML file some string, part of which should be recognized as JS code. What I mean is for example this:
<Render>
<![CDATA[<center><input type='checkbox' value=" + row[2] + " /></center>]]>
</Render>
Here I get this piece of data from a place in JavaScript where I have array row and I have index [2] but instead showing me the value of the element with this index the debugger shows me that the checkbox value is literally row[2] (not recognized as array).
The way I handle this in JavaScript is:
options.mRender = function (data, type, row) { return options.Render; };
where options.Render is the actual string <center><input type='checkbox' value=" + row[2] + " />.
I made a simple JSFiddle example. The idea is when I write person[0] to get Ivan instead of person[0] which is the result now.
I know that if I add eval() like this - $('#appnd').append(eval(txt)); but I can't figure out how to get use of this in my code since I'm passing the whole markup and not only the variable.
You could try something like this:
function parse(text) {
return text.replace(/[a-z]+\[\d+\]/g,function(exp){return eval(exp);});
}
JSFiddle
It simply takes the input and replaces parts of it that look like array[index] with whatever eval does with it.
This solution does not seem like a good idea to me and I agree that there should be some standard way of doing it (better), but I just can't think of another way of doing it.
Edit: It would probably be more reliable if you could mark the JS code in the XML somehow before it is sent to the client like <center><input type='checkbox' value=" + BEGINJS>row[2]<ENDJS + " /> then your regex wouldn't have to guess wildly at what the JS code will look like.

Escaping apostrophe in jQuery

I'm trying to escape out of some apostrophe's in my JSON. I know it's not ideal but i append the data to the DOM and call it later in the code. At the moment i get an error whenever there is an ' in the data. I've tried using replace and encodeURI but just doesnt seem to work.
My code basically looks like:
var addItem = function (item, target){
var obj = $(item).data('obj');
var obj_string = JSON.stringify(obj);
target.append("<div data-obj='" + obj_string + "'> Added </div>
}
When i inspect the element it breaks when it gets to the apostrophe:
{"publisher":"EA","games":[{"game":"Dragon's"}]}
Looks like this in the element inspector:
{"publisher":"EA","games":[{"game":"Dragon" s"}]}
And everything that follows is broken. Any ideas how i escape it?
I've found lots of ways if it was pureply jquery but with it being in the html it seems to not work.
You can avoid the escaping and stringification© using .data() to set the obj to the element directly.
$('<div/>').data('obj', obj).text('Added').appendTo(target);
Just keep in mind with this method you won't get a data attribute on the actual element itself but the data will be there when you request it with .data.
You are concatenating your content with a string that already uses single quotes. The concatenated result will most likely be <div data-obj='Dragon's'> which is not what you want.
Either escape the single quote when concatenating it (not sure the entity won't be interpreted):
.append("<div data-obj='" + obj_string.replace("'", "‚") + "'> Added </div>");
Or safer, you can build your nodes with jQuery which will give you a native escaping for some performance penalty:
.append($("<div>Added</div>").data("obj", obj_string));
Rather than leaving yourself open to XSS, try:
var div = document.createElement('div');
div.appendChild(document.createTextNode("Added"));
div.setAttribute("data-obj",obj_string);
target.append(div);

javascript onclick apostrophe quotation mark issue

Ok, I'm getting some data from an ajax call and need to store the value as a parameter to an onclick element via javascript.
Eg
output = "<a href = '#' onclick = 'deleteFileName('" + trim(splitString[i]) + "')'> delete File </a>";
This behaves strangely. When I inspect the element with chrome, the output looks like this
<a href="#" onclick="deleteFileName("0design mockup.xlsx')'> delete File </a>
It should obviously look like this
<a href = "#" onclick = "deleteFileName('0design mockup.xlsx')">
The parameter is a String so I need the quotes around it. This may not be the best way to do this, but why is it making the first two quotes double quotes and then the last two single quotes?
*This is a JSP server using ajax calls to gather information. The function "deleteFileName(fileNameIn)" is an ajax call. (I don't believe this is necessary information but you never know)
You can not use the same kinds of quotes for the value of onclick and for the function call. You need single quotes for one and double quotes for the other (where to put which should not matter). Otherwise you are closing the onclick attribute with the first single quote of the function call.
Example:
output = "<a href = '#' onclick = 'deleteFileName(\"" + trim(splitString[i]) + "\")'> delete File </a>";
Rather than inspecting the information, I suggest that you wget or curl the page directly (or use the browser's view-source function). These days I've found that many browsers present information subtly incorrectly in the inspector in their attempt to format everything nicely.
Removing the browser from the equation is a good first step, since that will show you exactly where the problem is occuring.

Error : "identifier starts immediately after numeric literal javascript"

$(obj).replaceWith('<a class="fd-tool-li" onclick="javascript:Like(this, #Model.User.HOCODE.ToString(), #Model.CommentHOCODE.ToString());">' +
'<i class="icon-thumbs-up"></i><span> ' +UserCount+ ' Like this</span>'+
'<a name="Unlike"class="fd-tool-li" onclick="javascript:Unlike(this, #Model.User.HOCODE.ToString(), #Model.CommentHOCODE.ToString());">(Unlike?)</a>' +
'</a>');
Why am I getting this error ?
Simplify your code to avoid quote problems (and improve readibility). Extract the onclick javascript from you replace call :
$(obj).html('<a class=fd-tool-li onclick="javascript:Like(this, #Model.User.HOCODE.ToString(), #Model.CommentHOCODE.ToString());">' +
'<i class="icon-thumbs-up"></i><span> ' +1+ ' Like this</span>'+
'<a name=Unlike class=fd-tool-li>(Unlike?)</a>' +
'</a>'
);
$(obj).click(function() {
// things
});
That's supposing the #Model is defined by a precompiler of some sort and isn't present in the code.
If that's really what your code looks like when it reaches the browser (as opposed to parts of it being handled on the server and something different going to the browser), then you have a syntax error where you have #Model.CommentHOCODE.ToString(). You'll need to fix that. Identifiers can't start with a #.
If instead that's processed server-side and replaced with a series of characters, you probably need to put quotes around it, if it's really a string.
Similarly, do you have a client-side variable called UserCount? Because if not, and if that isn't being processed server-side, that could be an issue as well.
Fundamentally you need to look at that code and establish what happens server-side and what the result is that gets sent to the client browser, then ensure that what gets sent to the client browser is valid.
in my case, I was using an UUID in order to set a complex variable (something + UUID) and an easy solution I did was:
Replace "-" by "", the uniqueness for the identifier keeps alive.
If you are using Razor (ASP.net) instead of doing this: #Model.User.HOCODE.ToString() try with: #(Model.User.HOCODE.ToString())
Regards.

Categories

Resources