Why is JSON.parse not working for "23232323."? - javascript

I have this field
text = "23232323."
and for validation I want to get it like this 23232323.
I am trying with JSON.parse(text) giving SyntaxError: JSON.parse: missing digits after decimal point
and eval(text) is giving 23232323
How can I fix it?

It can't be parsed because, contrary to popular belief, JSON is a strongly defined language and you can't simply put anything that you could eval.
Here's how numbers are defined :
(see json.org)
You can solve the problem by removing the dot at the end or, better, by not putting it in the first place. Of course, if you trust the source, you can simply use eval('('+yourstring+')') too.

Related

CL-WHO is always starting with a single quote

My issue is that CL-WHO begins each expression with a single quotation market when it turns the Lisp S-expressions into html output. This is okay most of the time, but it is an issue since I am linking my file to an external javascript file. I am trying to make this project simple, and since none of the javascript developers on my team know Common Lisp, using parenscript is likely out of the equation. Here is an example of my issue and one of the errors in my program:
:onclick "alertUser('id')"
When a particular element is pressed within the html document, this should trigger a JavaScript function called alertUser, and the id of the tag should be passed to the JavaScript function as an argument. But no matter what I do, CL-WHO will convert that string into single quotation marks, so I end up with an invalid expression. Here is what that code converts to:
onclick='alertUser('id')'>
Everything is a single quotation so 'alertUser(' is passed as the first string which is obviously invalid and I receive a syntax area in my developer tools. I thought that I could solve this problem by using the format function with escape characters. This would equate to:
CL-USER> (format t "\"alertUser('id')\"")
"alertUser('id')"
NIL
CL-USER>
But when I try that with CL-WHO:
:onclick (format nil "\"alertUser('id')\"")
That translates to:
onclick='"alertUser('locos-tacos-order')"'>
Which is also invalid html. As you can see, CL-WHO will start with a single quote no matter what. Next I tried the CL-WHO fmt function:
:onclick (fmt "\"alertUser('locos-tacos-order')\"")
When I use the fmt function it gets rid of my :onclick expression entirely when it is converted to html!:
id='id'"alertUser('id')">
Lastly I tried the str function, and got similarly invalid output to my original attempt:
onclick='"alertUser('id')"'
Obviously if I code this in pure html it will look like:
onclick="alertUser('id')">
Which is valid.
My question is simply how do I enable CL-WHO to use double quotation marks in these situations instead of single quotation marks?
#jkiiski was has the correct answer in the comments underneath my question, but I wanted to post the answer so that anyone with a similar issue in the future can resolve the problem. As #jkiiski said, there is a variable called ATTRIBUTE-QUOTE-CHAR in the cl-who package that defaults to #\'. You can simply set that variable to #\" instead in order for the default quotations used to be double quotation marks:
(setf *attribute-quote-char* #\")
After adding that line of code near the top of the file my html defaults to:
onclick="alertUser('id')"
and now the javascript can execute properly. Credit to #jkiiski for a correct answer.

Weird symbol in string breaks JSON.parse, but seems to be undetectable?

The description field is a text area field, somehow a user ended up with some strange little symbol in it. (see image)
When I grab this from the server, I assemble my data from the objects I grab, which includes the description on this object, and turn it into JSON string, and send it to my javascript.
From javascript, I JSON.parse it. But that weird little symbol causes the parse to fail. But, when you look at it, there is no character there or anything, yet it throws an undefined character in JSON.parse.
My response from the server has the description like this:
"blahblahtesttext\r\nslkdjf",
There is nothing but the expected \r\n......
But it has an unexpected token where that symbol is.
{"value":"blah blah test text//Symbol should be here, but there is nothing and it forces it to the next line
\r\nslkdjf","fieldType":"TEXTAREA","field":"Description"}
Where that symbol forces the string to the next line, which causes the issue.
Because I can't see what the actual character is... I do not know how to handle this.
Is there something that can strip out invalid characters in a JSON string so the parse works? I don't want to just try/catch this as it would toss out everything, I just want that weird invalid symbol to be stripped out.
Or is there a way to see what the actual character is that JSON.parse does not like?

 <-- here is that symbol for copy pasting into a string if you want to try parsing it.
EDIT:
I found that it was doing this in Notepad++
Where you can see that where the line separator was, it is placing actual carriage return and line feed there, breaking the string. It already has \r\n\r\n for the two returns that were placed in the actual text area after that line separator character.
But still unsure of how to deal with this, as that carriage return and line feed do not appear in the string as '\n\r', there is no character representation of them, but instead it actually puts a return there and breaks the string.
NEW EDIT:
Finally found something to get this working. I couldn't do a replace on that line separator character. When I pulled it from my database, it came through as a hidden carriage return. When you manually pressed 'Enter' in the text area, the string I got from the database would actually put a '\r\n' there. But the line separator did not.
So, I added these three lines before parsing to ensure I was escaping any invalid new lines/carriage returns.
result = result.replace(/\r\n/g, '\\r\\n');
result = result.replace(/\r/g, '\\r');
result = result.replace(/\n/g, '\\n');
The '\r\n' that were actually in the string would correctly be escaped already, which tripped me up because I didn't have to worry about escaping those until someone tried introducing this line separator....
As Xufox says, that appears to be U+2028. JSON.parse shouldn't fail on it since U+2028 doesn't require escaping in JSON; Chrome's doesn't, but that's probably because it's implementing this stage 4 proposal Xufox pointed out:
const o = {prop: "testing\u2028one two three"};
console.log(JSON.parse(JSON.stringify(o)));
If you need to work around a JSON.parse implementation that doesn't handle it, you could do this:
str = str.replace(/\u2028/g, "\\u2028");
...before running JSON.parse on str.

How to make string to json object

I have below string
'[{\'Question\': \'a Names and Roles (if known)\'}]'
I need to convert it into JSON.
I tried JSON.parse(s)
I got error SyntaxError: Unexpected token ' in JSON at position 2
and also
> eval(s)
SyntaxError: Unexpected string
Any help would be really appreciable
Problem is that you need to pass string inside JSON.parse(s).
Please make sure s is a string
'[{*Question\': at the point of asterisk you need a \' don't you?
So it should be
'[{\'Question\': \'a Names and Roles..
EDIT
Found this after a bit of research. Problem is with the single quote. Replace them with double quotes, you are good to go. See this fiddle, to check this out in action.
Additionally, I had to modify "[\'NA\']" in your string, to get it to working. That is also invalid JSON. If it is an array that you want it to be, you should put it like [\"NA\"].

regex replace on JSON is removing an Object from Array

I'm trying to improve my understanding of Regex, but this one has me quite mystified.
I started with some text defined as:
var txt = "{\"columns\":[{\"text\":\"A\",\"value\":80},{\"text\":\"B\",\"renderer\":\"gbpFormat\",\"value\":80},{\"text\":\"C\",\"value\":80}]}";
and do a replace as follows:
txt.replace(/\"renderer\"\:(.*)(?:,)/g,"\"renderer\"\:gbpFormat\,");
which results in:
"{"columns":[{"text":"A","value":80},{"text":"B","renderer":gbpFormat,"value":80}]}"
What I expected was for the renderer attribute value to have it's quotes removed; which has happened, but also the C column is completely missing! I'd really love for someone to explain how my Regex has removed column C?
As an extra bonus, if you could explain how to remove the quotes around any value for renderer (i.e. so I don't have to hard-code the value gbpFormat in the regex) that'd be fantastic.
You are using a greedy operator while you need a lazy one. Change this:
"renderer":(.*)(?:,)
^---- add here the '?' to make it lazy
To
"renderer":(.*?)(?:,)
Working demo
Your code should be:
txt.replace(/\"renderer\"\:(.*?)(?:,)/g,"\"renderer\"\:gbpFormat\,");
If you are learning regex, take a look at this documentation to know more about greedyness. A nice extract to understand this is:
Watch Out for The Greediness!
Suppose you want to use a regex to match an HTML tag. You know that
the input will be a valid HTML file, so the regular expression does
not need to exclude any invalid use of sharp brackets. If it sits
between sharp brackets, it is an HTML tag.
Most people new to regular expressions will attempt to use <.+>. They
will be surprised when they test it on a string like This is a
first test. You might expect the regex to match and when
continuing after that match, .
But it does not. The regex will match first. Obviously not
what we wanted. The reason is that the plus is greedy. That is, the
plus causes the regex engine to repeat the preceding token as often as
possible. Only if that causes the entire regex to fail, will the regex
engine backtrack. That is, it will go back to the plus, make it give
up the last iteration, and proceed with the remainder of the regex.
Like the plus, the star and the repetition using curly braces are
greedy.
Try like this:
txt = txt.replace(/"renderer":"(.*?)"/g,'"renderer":$1');
The issue in the expression you were using was this part:
(.*)(?:,)
By default, the * quantifier is greedy by default, which means that it gobbles up as much as it can, so it will run up to the last comma in your string. The easiest solution would be to turn that in to a non-greedy quantifier, by adding a question mark after the asterisk and change that part of your expression to look like this
(.*?)(?:,)
For the solution I proposed at the top of this answer, I also removed the part matching the comma, because I think it's easier just to match everything between quotes. As for your bonus question, to replace the matched value instead of having to hardcode gbpFormat, I used a backreference ($1), which will insert the first matched group into the replacement string.
Don't manipulate JSON with regexp. It's too likely that you will break it, as you have found, and more importantly there's no need to.
In addition, once you have changed
'{"columns": [..."renderer": "gbpFormat", ...]}'
into
'{"columns": [..."renderer": gbpFormat, ...]}' // remove quotes from gbpFormat
then this is no longer valid JSON. (JSON requires that property values be numbers, quoted strings, objects, or arrays.) So you will not be able to parse it, or send it anywhere and have it interpreted correctly.
Therefore you should parse it to start with, then manipulate the resulting actual JS object:
var object = JSON.parse(txt);
object.columns.forEach(function(column) {
column.renderer = ghpFormat;
});
If you want to replace any quoted value of the renderer property with the value itself, then you could try
column.renderer = window[column.renderer];
Assuming that the value is available in the global namespace.
This question falls into the category of "I need a regexp, or I wrote one and it's not working, and I'm not really sure why it has to be a regexp, but I heard they can do all kinds of things, so that's just what I imagined I must need." People use regexps to try to do far too many complex matching, splitting, scanning, replacement, and validation tasks, including on complex languages such as HTML, or in this case JSON. There is almost always a better way.
The only time I can imagine wanting to manipulate JSON with regexps is if the JSON is broken somehow, perhaps due to a bug in server code, and it needs to be fixed up in order to be parseable.

Parsing XFN data with Jquery, round 2

You guys already helped me on correctly parsing the REL attribute on A tags, but there are two XFN values that I'm not able to match:
"co-worker" and "co-resident". The hyphen causes an error with jquery.
I tried this
xfn_co-worker = $("a[rel~='co-worker']").length;
and this
xfn_co-worker = $("a[rel~='co\-worker']").length;
In both cases the error "Uncaught ReferenceError: Invalid left-hand side in assignment" is returned.
(Being these standard XFN values, I'm forces to use them)
Any idea is appreciated, as usual :-)
This isn't an error in you selector. The error lies in your variable name.
You can't use mathematical operators in the variable name. So the problem is your use of the - sign.
Try replacing
xfn_co-worker
with e.g
xfn_co_worker
And it should work alright
xfn_co_worker = $("a[rel~='co-worker']").length;
Note: Your variable name must match the following regex [a-zA-Z_$][0-9a-zA-Z_$]*

Categories

Resources