Why does JSON.parse("string") fail - json

According to the JSON spec a string is a legitimate JSON value.
So why does this happen?

You are actually passing the bare word string in to the the function which of course is not valid JSON. To actually pass in the value "string" you need to be careful with your JavaScript.
Try this:
JSON.parse("\"string\"")
The extra pair of quotes must be escaped so they become part of the value you pass in to the function.

The Syntax error tells you: "s" is an unexpected token. A string is a valid JSON value but as the spec describes it must be enclosed in double quotes.
string
""
" chars "
Generally, you can use JSON.stringify(myValue) to check what a properly formatted JSON string of such value would be.

Because a string in JSON must be surrounded by quotation marks, and in your JSON.parse("string") call, JSON.parse never "sees" any quotation marks as part of the text it is asked to parse. The double-quotes that we see are being used to form a legal string to pass in -- they're not part of the text we're passing in.
This call works:
JSON.parse('"s"')

Related

Convert JSON string to dictionary in ROBOT using json.loads() - why are triple quotes needed?

I've read that json.loads() can be used by Robot Framework to convert a JSON string to a dictionary in this post: Json handling in ROBOT
So if you define a dictionary-like string like this:
${json_string} Set Variable {"key1": "value1", "key2": "value2", "key3": "value3"}
You can then use the following to convert it to a dictionary:
${dict} Evaluate json.loads('''${json_string}''') json
My question is simple - why are the triple quotes needed here to surround the argument?
If single quotes are used an exception is thrown stating a string must be used:
${dict} Evaluate json.loads('${json_string}') json
(Edit) The above is a bad example, it actually works. If double quotes are used, though, it fails for SyntaxError: invalid syntax.
If no quotes at all are used an error occurs that indicates that the variable is a dictionary - but in Robot it isn't a dictionary (TypeError: the JSON object must be str, bytes or bytearray, not dict):
${dict} Evaluate json.loads(${json_string}) json
If Robot's Convert To String is used on the ${json_string} variable and then that new variable is passed to the json.loads() method the same TypeError occurs stating a string must be used, not a dictionary - but it has been converted to a string:
${json_string2} Convert To String ${json_string}
${dict} Evaluate json.loads(${json_string2}) json
What are the triple quotes accomplishing that are not being accomplished by the other two? This seems to be an aspect of Robot framework...
I'll go ahead and follow up in an answer since it's simpler that way, I think does answer your follow-up question in this comment.
I'm not very familiar with Robot Framework but if I understand correctly all it's doing in .robot files when you use ${variable} substitution is simple string templating: so when you pass a ${variable} into an expression, no matter what type the underlying variable is, it always substitutes its string representation, so the expression you're trying to evaluate is literally:
json.loads({'key': "value1', 'key2': 'value2'})
This is why you need the """ (in principle you could use just ", but """ would be much safer). Incidentally, if you converted the above dict to its standard string representation in Python it would not be valid JSON, because JSON requires double-quotes not single-quotes.
The official documentation on this is a little confusing and seems to contradict itself (I think it was not written by a native English speaker which is OK):
When a variable is used in the expressing using the normal ${variable} syntax, its value is replaces before the expression is evaluated. This means that the value used in the expression will be the string representation of the variable value, not the variable value itself. This is not a problem with numbers and other objects that have a string representation that can be evaluated directly, but with other objects the behavior depends on the string representation.
I say it contradicts itself because first is says "its value [is replaced] before the expression is evaluated". But then it says "the value used in the expression will be the string representation of the variable value" (which is not the same as the value itself). The latter explanation seems to be the correct one though.
However, it seems with Evaluate you can also use the syntax $variable to replace the literal value of the variable instead of its string representation:
Starting from Robot Framework 2.9, variables themselves are automatically available in the evaluation namespace. They can be accessed using special variable syntax without the curly braces like $variable. These variables should never be quoted, and in fact they are not even replaced inside strings.
But in your case you wrote:
${json_string} Set Variable {"key1": "value1", "key2": "value2", "key3": "value3"}
As I understand it "Set Variable" just stores the value as a string literal. So indeed it should suffice then to run (as you did):
${dict} Evaluate json.loads('''${json_string}''') json
In your final example "Convert To String" is not doing anything, because as you wrote ${json_string} already replaces as a string. You just have to understand that the result of json.loads(${json_string}) is a Python expression where ${json_string} is just replaced literally with the contents of that template variable--it is not the same as passing a str value to json.loads(). The latter I believe may be achievable as
${dict} Evaluate json.loads($json_string) json
at least, going by the docs. But I have not tested this.

Why this Arduino sscanf JSON parsing problem?

I am trying to parse this JSON string:
{"FN":"142","SName":"stil.mp3","InPlaylist1":"1","InPlaylist2":"1","error":0}
I use this sscan statement:
' RetScanf = sscanf(OneJsonStr, "{\"FN\":\"%d\",\"SName\":\"%[^\"],\"InPlaylist1\":\"%d\",\"InPlaylist2\":\"%d\",\"error\":%d}", &Parameter1_FNo, Parameter2_FName, InP1, InP2, &err); '
but in only parses the two first parameter "FN" and "SName". any idea what I am doing wrong?
thnaks in advance
br.
Allan
In your sscanf() format, when matching the SName string, you never try to match the trailing double quote.
,\"SName\":\"%[^\"]\",
Also, since the format says that InP1/2 are integers, you should pass in their addresses (assuming they aren't already pointers).

Clojure: Escaping unicode `\U` in JSON encoding

Postamble for future readers
Elm allows literal C:\Users\myuser in strings
This is consistent with the JSON spec
My problem was unrelated to this, but several layers of escaping convoluted the problem. Future lesson: fully producing a minimal working example would have found the error!
Original question
I have a Clojure backend that talks to an Elm frontend. I hit a bump when decoding JSON values in Elm.
\U below means the literal characters backslash and U, as if read from a text file. "\\U" is the same string as input in Clojure and Elm source (\ must be escaped). Note enclosing "".
Problem: encoding \U
The literal string \U, escaped "\\U" is not accepted by the Elm string decoder.
A blog post suggests that to obtain the literal string \U, this should be encoded in source code as "\\\\U", "escaping the unicode escape".
The literal string I want to send to the client is C:\Users\myuser. I prefer to send valid JSON from the server to the client.
Clojure standard library behavior
clojure.data.json does not do anything special for strings containing the literal \U. The example below shows that \U and \m are threated equally, the backslash is escaped, and the following character ignored.
project.core> (clojure.data.json/write-str "C:\\Users\\myuser")
"\"C:\\\\Users\\\\myuser\""
Manual workaround
Temporary workaround is manually escaping the strings I need:
(defn escape-backslash-u [s]
(clojure.string/replace s "\\U" "\\\\U"))
Concrete questions
Is clojure.data.json/write-str behaving correctly? As I understand the documentation, output should be valid unicode.
Are other JSON libraries behaving similarly?
Is Elm's Json.Decode behaving correctly by rejecting the literal string \U?
Solution progress
A friendly Clojurians Slack user pointed to the JSON standard specification, specifically sections 7. Strings and 8.2. Unicode characters.
I think you may be on the wrong track here.
The string you gave as an example, "C:\\Users\\myuser" is completely unproblematic, it does not contain any Unicode escape sequences. It is a string containing the ASCII characters ‘C’, ‘:’, ‘\’, ‘U’, and so on. The backslash is the escape character in Clojure strings so it needs to be escaped itself to represent a literal backslash.
In any case the string "C:\\Users\\myuser" can be serialized with (clojure.data.json/write-str "C:\\Users\\myuser"), and, as you know, this gives "\"C:\\\\Users\\\\myuser\"". All of this seems perfectly straightforward and sound.
Printing "\"C:\\\\Users\\\\myuser\"" results in the original string "C:\\Users\\myuser" being printed. That string is accepted as valid by JSONLint, again as expected.
I understood it as Elm beeing unable to decode \"C:\\\\User... to "C:\\User... because it interprets \u as start for an escape sequence.
I tried elm here with the following code:
import Html exposing (text)
main =
text "\"c:\\\\user\\\\foo\"" // from clojure.data.json/write-str
which in turn compiles/runs to
"c:\\user\\foo"
which looks fine to me.
Are you sure there is nothing else going on (middleware, transport) ?

Omnifaces Escape JSON Strings

Is there a way to escape text for using in a json expression with Omnifaces:
e.g:
"reviewBody": "#{of:escapeJS(reviewBean.text)}"
This appears to escape single quotes but I want to escape double quotes.
For JSON encoding in EL, use #{of:toJson} instead (introduced in OmniFaces 1.5).
"reviewBody": #{of:toJson(reviewBean.text)}
Note that it already takes care of doublequotes. This function not only deals with CharSequence (String and friends), but also properly deals with Number, Boolean, Date, Object[], Collection, Map and even true Javabeans. Basically, you can encode "everything" with it without worrying about the format and quoting. See also the showcase, javadoc and source code.

JSON.stringify() not escaping apostrophe

...using JSON2.js and JQUERY
as you can see from the first image the object property customerReport.Title has an apostrophe. In the code you can see that I'm calling JSON.stringify() into reportAsJson string which still has the unescaped apostrophe.
the error returned by $.ajax() is {"Message":"Invalid object passed in, \u0027:\u0027 or \u0027}\u0027 expected. ...
Initially I'm just going to ban apostrophe's from the user, but I thought JSON.stringify() handled this or do I need to set some option????
Thanks
You can avoid removing these apostrophes replacing them with an HTML entity ' - that's a single quot - and later decode HTML entities either in the client or server-side.
Following has worked for me after so many failed tries for stringify and other JSON parsing functions:
updatedString = string.replace(/('[a-zA-Z0-9\s]+\s*)'(\s*[a-zA-Z0-9\s]+')/g,"$1\\\'$2");
where
string = string having apostrophe in it.
updatedString = string with apostrophe issue resolved/escaped