How to correctly handle an Unterminated string exception? - javascript

I'm using the JSON.org java library to tinker with.
At the moment I'm encountering an error because of \n characters:
try{
String s = "{\"property:\":\"line1\n,line2\"}";
JSONObject o = new JSONObject(s);
}catch(Exception e){
e.printStackTrace(System.err);
}
results in:
org.json.JSONException: Unterminated string at 20 [character 0 line 2]
at org.json.JSONTokener.syntaxError(JSONTokener.java:433)
at org.json.JSONTokener.nextString(JSONTokener.java:261)
at org.json.JSONTokener.nextValue(JSONTokener.java:361)
at org.json.JSONObject.<init>(JSONObject.java:218)
at org.json.JSONObject.<init>(JSONObject.java:325)
After doing a quick search I found this answer
which points to my string having to be escaped like so:
String s = "{\"property:\":\"line1\\n,line2\"}";
I would no longer see the exception and could do a string replace for "\n" with '\n', but I'm just wondering:
is the recommended way of dealing with new lines in a JSON string in java ?

As you can see in the JSON specification, JSON does not allow real line breaks in strings, so you always need to escape newline characters with \n. This is not a special Java thing. See also this question.

Related

JSON.parse(), why this escape character returns an error?

I am trying to learn more about the core functionality of the JSON.parse() method, but I cannot understand why this string returns an error:
JSON.parse('["foo\\"]'); // > "Unexpected end of input"
Why does this not return ["foo\"]?
Because the string isn't terminated, because the second " is escaped by \, because the data you're parsing is:
["foo\"]
You can confirm this yourself with
var s = '["foo\\"]';
alert(s); // or
console.log(s);
This is because of the cumulative escape action of \ in JS and JSON level in your expression.
Your string ["foo\\"]
Escaped by JS to be ["foo\"] first because its double \\
Now it is sent to JSON.parse like ["foo\"] which escapes the "
So, it is an un-terminated string for JSON parser.
If you need to parse ["foo\\"] in json level, assemble the js string to be escaped to this. Which is ["foo\\\\\"].
TEST.
s = '["foo\\\\\"]';
console.log(s); //'["foo\\"]'
console.log(JSON.parse(s);) // ["foo\"]

JSON Parse error: Unterminated string

I've met an usual problem when escaping a quote within the JSON parse function. If the escaped quote is present, in this case 'test"', it causes the following error 'SyntaxError: JSON Parse error: Unterminated string'.
var information = JSON.parse('[{"-1":"24","0":"","1":"","2":"","3":"0.0000","4":"","5":"0.00","6":"0.00","7":"1.00","8":"0","9":"false","10":"false","11":[""],"12":"","13":"","14":"test\""}]');
JSON Lint validates the JSON as valid.
You'll have to double escape it, as in "test\\""
var information = JSON.parse('[{"-1":"24","0":"","1":"","2":"","3":"0.0000","4":"","5":"0.00","6":"0.00","7":"1.00","8":"0","9":"false","10":"false","11":[""],"12":"","13":"","14":"test\\""}]');
document.body.innerHTML = '<pre>' + JSON.stringify(information, null, 4) + '</pre>';
The first backslash escapes the second backslash in the javascript string literal.
The second backslash escapes the quote in the JSON string literal.
So it's parsed twice, and needs escaping twice.
So even if it's valid JSON, you'll need one escape for javascript string literals that escapes the escape used in JSON.
var information = JSON.parse('[{"-1":"24","0":"","1":"","2":"","3":"0.0000","4":"","5":"0.00","6":"0.00","7":"1.00","8":"0","9":"false","10":"false","11":[""],"12":"","13":"","14":"test\\""}]');
Putting doubleslash worked for me...at least in console..give it a try..
I fixed this problem in my spring boot app with #RestController by Using #IgnoreJson
--------- class book ---------------
#OneToMany(mappedBy = "book")
private Set<Chapitre> chapitres = new TreeSet<>();
--------- class chapitre -----------
#ManyToOne(cascade = CascadeType.MERGE)
#JsonIgnore
private Book book;
Here is the issue : use \' instead of \" at last array of object
\"
\'

Javascript - strip out occurrences of u' in JSON string, parse is returning unexpected token

I have a textfield in a database that contains the results of a python json.dumps(list_instance) operation. As such, the internal fields have a u' prefix, and break the browser's JSON.parse() function.
An example of the JSON string is
"density": "{u'Penobscot': 40.75222856500098, u'Sagadahoc':
122.27083333333333, u'Lincoln': 67.97977755308392, u'Kennebec':
123.12237174095878, u'Waldo': 48.02117802779616, u'Cumberland':
288.9285325791363, u'Piscataquis': 3.9373586457405247, u'Hancock':
30.698239582715903, u'Washington': 12.368718341168325, u'Aroostook':
10.827378163074039, u'York': 183.47612497543722, u'Franklin':
16.89330963710371, u'Oxford': 25.171240748402518, u'Somerset':
12.425648288323485, u'Knox': 108.48302300109529, u'Androscoggin':
208.75502815768303}"
What I'd like to do is replace those occurrences of u' with a '(single-quote). I've tried
function renderValues(data){
var pop = JSON.parse(data.density.replace(/u'/g, "'"));
}
but I'm always getting a unexpected token ' exception. Since many of the possible key fields may contain a u, it is not feasable to just delete that character. How can I find all instances of u' and replace with ' without getting the exception?
The accepted solution is wrong. Your code fails because that string is not valid JSON. Fixing the pseudo-JSON string by replacing it is wrong.
What you have to do is fix the python code that is producing that broken JSON string, which I am pretty sure it is a str() or unicode() where there should be nothing. What you have as a value for the key "density" is a string instead of a dictionary, and therefore, python returns you something like the following:
{"density": "a string that looks like JSON but it is in fact a string reprensentation of a dictionary"}
The function json.dumps will return you always valid JSON strings.
Fix that and you will not have to hack around with filthy string replacements or whatever.
EDIT
Check the following snippet out. There you can see that the u'...' is just the python readable-representation of a unicode object, and has nothing to do whatsoever with a JSON serialization.
>>> import json
>>> data = {u'name': u'Manuel', u'age': 26}
>>> print data
{u'age': 26, u'name': u'Manuel'} # this is the python representation of a dictionary
>>> print json.dumps(data)
{"age": 26, "name": "Manuel"} # this is a valid JSON string
That JSON is not properly formed, as easy as that.
Updated solution: replace(/u'/g, "'")); => replace(/u'(?=[^:]+')/g, "'"));.
Tested with the following:
"{u'Penobscot': 40.75222856500098, u'Sagadahoc': 122.27083333333333, u'Lincoln': 67.97977755308392, u'Kennebec': 123.12237174095878, u'Waldo': 48.02117802779616, u'Cumberland': 288.9285325791363, u'Piscataquis': 3.9373586457405247, u'Hancock': 30.698239582715903, u'Timbuktu': 12.368718341168325, u'Aroostook': 10.827378163074039, u'York': 183.47612497543722, u'Franklin': 16.89330963710371, u'Oxford': 25.171240748402518, u'Somerset': 12.425648288323485, u'Knox': 108.48302300109529, u'Androscoggin': 208.75502815768303}".replace(/u'(?=[^:]+')/g, "'");
results in:
"{'Penobscot': 40.75222856500098, 'Sagadahoc': 122.27083333333333, 'Lincoln': 67.97977755308392, 'Kennebec': 123.12237174095878, 'Waldo': 48.02117802779616, 'Cumberland': 288.9285325791363, 'Piscataquis': 3.9373586457405247, 'Hancock': 30.698239582715903, 'Timbuktu': 12.368718341168325, 'Aroostook': 10.827378163074039, 'York': 183.47612497543722, 'Franklin': 16.89330963710371, 'Oxford': 25.171240748402518, 'Somerset': 12.425648288323485, 'Knox': 108.48302300109529, 'Androscoggin': 208.75502815768303}"
a little bit old in the answer but if there is no way to change or access the server response try with:
var strExample = {'att1':u'something with u'};
strExample.replace(/u'[\}|\,]/g, "ç'").replace(/u'/g, "'").replace(/ç'/g, "u'");
//{'att1':'something with u'};
The first replace will handle the u' that are in the trailing part of the string in the object changing it to 'ç' character
then removing the u from the phyton unicode and finally change it to u' like the original
I had a similar issue and made this regex that found all of the u's even if the values had them too.
replace(/(?!\s|:)((u)(?='))/g, "")
The accepted answer, I found, missed these occurrences.
I know the OP's doesn't have 'u' for the values and only for keys but thought this may be useful too :)

Why are endline characters illegal in HTML string sent over ajax?

Within HTML, it is okay to have endline characters. But when I try to send HTML strings that have endline characters over AJAX to have them operated with JavaScript/jQuery, it returns an error that says that endline characters are illegal. For example, if I have a Ruby string:
"<div>Hello</div>"
and jsonify it with Ruby by to_json, and send it over ajax, parse it within JavaScript by JSON.parse, and insert that in jQuery like:
$('body').append('<div>Hello</div>');
then it does not return an error, but if I do a similar thing with a string like
"<div>Hello\n</div>"
it returns an error. Why are they legal in HTML and illegal in AJAX? Are there any other differences between a legal HTML string loaded as a page and legal HTML string sent over ajax?
string literals can contain line breaks, they just need to be escaped with a backslash like so:
var string = "hello\
world!";
However, this does not create a line break in the string, as it must be an explicit \n escape sequence. This would technically become helloworld. Doing
var string = "hello"
+ "world"
would be much cleaner
Specify the type of the ajax call as 'html'. Jquery will try to infer the type when parsing the response.
If the response is json, newlines should be escaped.
I'd recommend using a library to serialize json. You're unlikely to handle all the edge cases if you roll your own.
Strings in JavaScript MUST appear on a single line, with the exception of escaping that line:
var str = "abc \
def";
However note that the newline is escaped and will not appear in the string itself.
The best option is \n, but note that if it is already going through something that parses \n then you will need to double-escape it as \\n.
Seeing how you're already escaping the JSON properly by using to_json in Ruby, I do believe the bug is in jQuery; when there are newlines in the string it has trouble determining whether you meant to create a single element or a document fragment. This would work just fine:
var str = "<div>Hello\n</div>";
var wrapper = document.createElement('div');
wrapper.innerHTML = str;
$('body').append(wrapper);
Demo

jQuery.parseJSON throws “Invalid JSON” error due to escaped single quote in JSON

I’m making requests to my server using jQuery.post() and my server is returning JSON objects (like { "var": "value", ... }). However, if any of the values contains a single quote (properly escaped like \'), jQuery fails to parse an otherwise valid JSON string. Here’s an example of what I mean (done in Chrome’s console):
data = "{ \"status\": \"success\", \"newHtml\": \"Hello \\\'x\" }";
eval("x = " + data); // { newHtml: "Hello 'x", status: "success" }
$.parseJSON(data); // Invalid JSON: { "status": "success", "newHtml": "Hello \'x" }
Is this normal? Is there no way to properly pass a single quote via JSON?
According to the state machine diagram on the JSON website, only escaped double-quote characters are allowed, not single-quotes. Single quote characters do not need to be escaped:
Update - More information for those that are interested:
Douglas Crockford does not specifically say why the JSON specification does not allow escaped single quotes within strings. However, during his discussion of JSON in Appendix E of JavaScript: The Good Parts, he writes:
JSON's design goals were to be minimal, portable, textual, and a subset of JavaScript. The less we need to agree on in order to interoperate, the more easily we can interoperate.
So perhaps he decided to only allow strings to be defined using double-quotes since this is one less rule that all JSON implementations must agree on. As a result, it is impossible for a single quote character within a string to accidentally terminate the string, because by definition a string can only be terminated by a double-quote character. Hence there is no need to allow escaping of a single quote character in the formal specification.
Digging a little bit deeper, Crockford's org.json implementation of JSON for Java is more permissible and does allow single quote characters:
The texts produced by the toString methods strictly conform to the JSON syntax rules. The constructors are more forgiving in the texts they will accept:
...
Strings may be quoted with ' (single quote).
This is confirmed by the JSONTokener source code. The nextString method accepts escaped single quote characters and treats them just like double-quote characters:
public String nextString(char quote) throws JSONException {
char c;
StringBuffer sb = new StringBuffer();
for (;;) {
c = next();
switch (c) {
...
case '\\':
c = this.next();
switch (c) {
...
case '"':
case '\'':
case '\\':
case '/':
sb.append(c);
break;
...
At the top of the method is an informative comment:
The formal JSON format does not allow strings in single quotes, but an implementation is allowed to accept them.
So some implementations will accept single quotes - but you should not rely on this. Many popular implementations are quite restrictive in this regard and will reject JSON that contains single quoted strings and/or escaped single quotes.
Finally to tie this back to the original question, jQuery.parseJSON first attempts to use the browser's native JSON parser or a loaded library such as json2.js where applicable (which on a side note is the library the jQuery logic is based on if JSON is not defined). Thus jQuery can only be as permissive as that underlying implementation:
parseJSON: function( data ) {
...
// Attempt to parse using the native JSON parser first
if ( window.JSON && window.JSON.parse ) {
return window.JSON.parse( data );
}
...
jQuery.error( "Invalid JSON: " + data );
},
As far as I know these implementations only adhere to the official JSON specification and do not accept single quotes, hence neither does jQuery.
If you need a single quote inside of a string, since \' is undefined by the spec, use \u0027 see http://www.utf8-chartable.de/ for all of them
edit: please excuse my misuse of the word backticks in the comments. I meant backslash. My point here is that in the event you have nested strings inside other strings, I think it can be more useful and readable to use unicode instead of lots of backslashes to escape a single quote. If you are not nested however it truly is easier to just put a plain old quote in there.
I understand where the problem lies and when I look at the specs its clear that unescaped single quotes should be parsed correctly.
I am using jquery`s jQuery.parseJSON function to parse the JSON string but still getting the parse error when there is a single quote in the data that is prepared with json_encode.
Could it be a mistake in my implementation that looks like this (PHP - server side):
$data = array();
$elem = array();
$elem['name'] = 'Erik';
$elem['position'] = 'PHP Programmer';
$data[] = json_encode($elem);
$elem = array();
$elem['name'] = 'Carl';
$elem['position'] = 'C Programmer';
$data[] = json_encode($elem);
$jsonString = "[" . implode(", ", $data) . "]";
The final step is that I store the JSON encoded string into an JS variable:
<script type="text/javascript">
employees = jQuery.parseJSON('<?=$marker; ?>');
</script>
If I use "" instead of '' it still throws an error.
SOLUTION:
The only thing that worked for me was to use bitmask JSON_HEX_APOS to convert the single quotes like this:
json_encode($tmp, JSON_HEX_APOS);
Is there another way of tackle this issue? Is my code wrong or poorly written?
Thanks
When You are sending a single quote in a query
empid = " T'via"
empid =escape(empid)
When You get the value including a single quote
var xxx = request.QueryString("empid")
xxx= unscape(xxx)
If you want to search/ insert the value which includes a single quote in a query
xxx=Replace(empid,"'","''")
Striking a similar issue using CakePHP to output a JavaScript script-block using PHP's native json_encode. $contractorCompanies contains values that have single quotation marks and as explained above and expected json_encode($contractorCompanies) doesn't escape them because its valid JSON.
<?php $this->Html->scriptBlock("var contractorCompanies = jQuery.parseJSON( '".(json_encode($contractorCompanies)."' );"); ?>
By adding addslashes() around the JSON encoded string you then escape the quotation marks allowing Cake / PHP to echo the correct javascript to the browser. JS errors disappear.
<?php $this->Html->scriptBlock("var contractorCompanies = jQuery.parseJSON( '".addslashes(json_encode($contractorCompanies))."' );"); ?>
I was trying to save a JSON object from a XHR request into a HTML5 data-* attribute. I tried many of above solutions with no success.
What I finally end up doing was replacing the single quote ' with it code ' using a regex after the stringify() method call the following way:
var productToString = JSON.stringify(productObject);
var quoteReplaced = productToString.replace(/'/g, "'");
var anchor = '<a data-product=\'' + quoteReplaced + '\' href=\'#\'>' + productObject.name + '</a>';
// Here you can use the "anchor" variable to update your DOM element.
Interesting. How are you generating your JSON on the server end? Are you using a library function (such as json_encode in PHP), or are you building the JSON string by hand?
The only thing that grabs my attention is the escape apostrophe (\'). Seeing as you're using double quotes, as you indeed should, there is no need to escape single quotes. I can't check if that is indeed the cause for your jQuery error, as I haven't updated to version 1.4.1 myself yet.

Categories

Resources