Omnifaces Escape JSON Strings - json

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.

Related

Raw string field value in JSON file

In my JSON file, one of the fields has to carry the content of another file (a string).
The string has CRLFs, single/double quotes, tabs.
Is there a way to consider my whole string as a raw string so I don't have to escape special characters?
Is there an equivalent in JSON to the string raw delimiter in C++?
In C++, I would just put the whole file content inside : R"( ... )"
Put simply, no there isn't. Depending on what parser you use, it may have a feature that allows this and/or there may be a variant of JSON that allows this (examples of variants include JSONP and JSON-C, though I'm not aware of one specifically that allows for the features you are looking for), but the JSON standard ubiquitous on the web does not support multiline strings or unescaped special characters.
A workaround for the lack of raw string support in JSON is to Base64 encode your string before adding it to your JSON.

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) ?

Why does JSON.parse("string") fail

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"')

Does Jackson JSON do special char escaping?

I was assuming that Jackson would automatically escape special characters during serialization i.e. serialize "/path/" as "\/path\/". It appears not to be the case - at least out of the box with 1.6:
#Test
public void testJacksonSerialize() throws Exception
{
ObjectMapper om = new ObjectMapper();
assertEquals("\\/path\\/", om.writeValueAsString("/path/"));
}
...fails - the output produced is "/path/". Do I have to write my own serializer or is there a way to enable special char escaping in Jackson?
thanks,
-nikita
Jackson only escapes mandatory things. "/" is not something you must escape, hence it is not. This as per JSON specification.
Now: if you absolutely want escaping, you can use methods to write "raw" content or values (in which case Jackson does no processing whatsoever and dumps String in output).
But do you really need such escaping? I know some generators do escape it (for reasons unknown to me), but no parser expects it so it should be just fine to leave slashes unescaped. This is different from backslashes that obviously must be escaped.
The slash "/" doesn't need to be escaped in JSON because it has no special meaning. Yet JSON allows the slash to be escaped for the following reason.
If you dump a JSON text right into a <SCRIPT> element of an HTML text, you have to make sure that the two-character-sequence "</" does not occur in the text. That sequence would end the script element immediately according to HTML rules. But if the JSON text reads "<\/", this has the same meaning to JSON while not interferring with HTML rules. Consequently, some JSON generators escape the slash if and only if it's preceded by a less-than-sign.
That being said, I don't know the direct answer to your question (how to absolutely do the escaping in Jackson).
New line character will not work in case of Tooltip with some browsers.
Not working \r\n Not working or \n Not working
Use double backslash to skip characters
Solution : use '\\r\\n' in place of '\r\n' ,
it will solve your problem.

Do the JSON keys have to be surrounded by quotes?

Example:
Is the following code valid against the JSON Spec?
{
precision: "zip"
}
Or should I always use the following syntax? (And if so, why?)
{
"precision": "zip"
}
I haven't really found something about this in the JSON specifications. Although they use quotes around their keys in their examples.
Yes, you need quotation marks. This is to make it simpler and to avoid having to have another escape method for javascript reserved keywords, ie {for:"foo"}.
You are correct to use strings as the key. Here is an excerpt from RFC 4627 - The application/json Media Type for JavaScript Object Notation (JSON)
2.2. Objects
An object structure is represented as a pair of curly brackets
surrounding zero or more name/value pairs (or members). A name is a
string. A single colon comes after each name, separating the name
from the value. A single comma separates a value from a following
name. The names within an object SHOULD be unique.
object = begin-object [ member *( value-separator member ) ] end-object
member = string name-separator value
[...]
2.5. Strings
The representation of strings is similar to conventions used in the C
family of programming languages. A string begins and ends with
quotation marks. [...]
string = quotation-mark *char quotation-mark
quotation-mark = %x22 ; "
Read the whole RFC here.
From 2.2. Objects
An object structure is represented as a pair of curly brackets surrounding zero or more name/value pairs (or members). A name is a string.
and from 2.5. Strings
A string begins and ends with quotation marks.
So I would say that according to the standard: yes, you should always quote the key (although some parsers may be more forgiving)
Yes, quotes are mandatory. http://json.org/ says:
string
""
" chars "
Not if you use JSON5
For regular JSON, yes keys must be quoted. But if you need otherwise, checkout widely used JSON5, which is so-named because is a superset of JSON that allows ES5 syntax, including:
unquoted property keys
single-quoted, escaped and multi-line strings
alternate number formats
comments
extra whitespace
The JSON5 reference implementation (json5 npm package) provides a JSON5 object that has parse and stringify methods with the same args and semantics as the built-in JSON object.
widely used, and depended on by many high profile projects
JSON5 was started in 2012, and as of 2022, now gets >65M downloads/week, ranks in the top 0.1% of the most depended-upon packages on npm, and has been adopted by major projects like Chromium, Next.js, Babel, Retool, WebStorm, and more. It's also natively supported on Apple platforms like MacOS and iOS.
~ json5.org homepage
In your situation, both of them are valid, meaning that both of them will work.
However, you still should use the one with quotation marks in the key names because it is more conventional, which leads to more simplicity and ability to have key names with white spaces etc.
Therefore, use the one with the quotation marks.
edit// check this: What is the difference between JSON and Object Literal Notation?
Since you can put "parent.child" dotted notation and you don't have to put parent["child"] which is also valid and useful, I'd say both ways is technically acceptable. The parsers all should do both ways just fine. If your parser does not need quotes on keys then it's probably better not to put them (saves space). It makes sense to call them strings because that is what they are, and since the square brackets gives you the ability to use values for keys essentially it makes perfect sense not to.
In Json you can put...
>var keyName = "someKey";
>var obj = {[keyName]:"someValue"};
>obj
Object {someKey: "someValue"}
just fine without issues, if you need a value for a key and none quoted won't work, so if it doesn't, you can't, so you won't so "you don't need quotes on keys". Even if it's right to say they are technically strings. Logic and usage argue otherwise. Nor does it officially output Object {"someKey": "someValue"} for obj in our example run from the console of any browser.