Garrett said:
That would require more code to be downloaded and more processing to run
it. What about mobile devices?
You are confused. What good is shorter code that is not a solution?
var isValidJSON = /^[\],:{}\s]*$/.
test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
replace(
/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
']').
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))
Is this from json2.js? If yes, then it is not acceptable. To begin
with, it does not regard "\"" valid JSON even though it is.
The code is from json2.js:
http://www.json.org/json2.js
Then it must be either summarily dismissed, or updated at least as follows:
/"([^"\\]|\\.)*"|.../
because *that* is the proper way to match a double-quoted string with
optional escape sequences. Refined for JSON, it must be at least
/"([^"\\^\x00-\x1F]|\\["\\\/bfnrt]|\\u[0-9A-Fa-f]{4})*"|.../
There is a problem; TAB character code is 9 and all implementations
allow it.
I see you went from unicode escape sequences to hex escapes, but why
\x00 and not \x0? Or why not just use a decimal escape \0?
The character range could be written more compactly; instead of
[0-9A-Fa-f], [0-9A-f], or even just [0-f], if that is not considered too
unreadable. Though similar in appearance, it could not be `[o-f]`
because that would be result in a SyntaxError, thrown by CharacterRange,
step 6. If i > j then throw a SyntaxError exception.
I haven't tested it, yet. More on testing below...
// Untested.
var jsonStringExp =
/"\t|(?:[^"\\^\0-\x1F]|\\["\\\/bfnrt]|\\u[0-f]{4})*"/,
// DecimalIntegerLiteral ::
// 0 NonZeroDigit DecimalDigitsopt
// JSONNumber:
// -opt DecimalIntegerLiteral JSONFractionopt ExponentPartopt
jsonNumberExp = /-?(0|[1-9]+)(?:\.\d+)?(?:[eE][+\-]\d+)?/,
jsonPrimitiveExp = new RegExp(
jsonStringExp.source
+ "|" + jsonNumberExp.source
+ "|true|false|null", "g"
);
var passExp = /^[\],:{}\s]*$/;
function isInvalidJson(text) {
var filtered = text.replace(jsonPrimitiveExp, ']')
.replace(/(?:^|:|,)(?:\s*\[)+/g, '')
.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g);
return passExp.test(filtered);
}
That is gibberish. Either it is JSON, or it is ECMAScript.
Not gibberish.
ECMAScript defines JSON for ECMAScript. When I refer to JSON in
ECMAScript, I am referring to the JSON Grammar defined in ECMAScript 5.
JSON Grammar in ECMAScript 5 differs from the grammar specified in RFC
4627 in that it allows primitive values at top-level.
I don't think so.
What you've allowed in your RegExp doesn't match JSON Grammar defined in
ECMA 5.
"\"" is both an ES string literal and JSON for the string containing"
Yes.
"\\\"" is both an ES string literal and JSON for the string containing \"
Yes.
"\\"" is neither an ES string literal nor JSON.
Correct.
But that was not the purpose of the JSON string.
What do you mean by the purpose of the JSON String? The purpose is
inside the programmer.
Yes, but that is not how JSON is usually being put in. That is, the
escaping backslash is _not_ escaped then, and the characters that
quoteMarkInJSONString contains are
\"
Right; a JSONValue is usually going to be supplied as a value of an
identifier, e.g. xhr.responseText. A string value having the character
sequence - "\"" - is valid JSON.
That would be invalid.
whereas only the latter was intended.
A JSON string *literal* may very well contain a literal backslash character,
and it may also contain a literal double quote. The expression fails to
recognize that.
No, a JSONString may not contain a literal backslash character.
| JSONString ::
| "JSONStringCharactersopt "
|
| JSONStringCharacters ::
| JSONStringCharacter JSONStringCharactersopt
|
| JSONStringCharacter ::
| SourceCharacter but not double-quote " or backslash \ or U+0000 thru
| U+001F \ JSONEscapeSequence
JSONStringCharacter may not contain backslash unless that is part of a
JSONEscapeSequence.
| JSONEscapeSequence ::
| JSONEscapeCharacter
| UnicodeEscapeSequence
[...]
I don't think so. My understanding of the intent of json2.js comes from
code comments in it.
| // We split the second stage into 4 regexp operations in order to
| // work around crippling inefficiencies in IE's and Safari's regexp |
| // engines. First we replace the JSON backslash pairs with '@' (a
| // non-JSON character).
Replaces backslash chars with "@", which is excluded by /^[\],:{}\s]*$/
[...] The suggestion to use an object literal as the string to the
argument to JSON.parse is not any better than using "true".
But it is. It places further requirements on the capabilities of the
parser. An even better test would be a combination of all results of
all productions of the JSON grammar.
Cases that are known to be problematic can be filtered.
Your point being?
My point is that instead of trying every possible valid grammar check,
known bugs -- such as allowing 1. and +1 and 01, as seen in Spidermonkey
-- could be checked.
The purpose of this was to provide a viable fallback for JSON.parse().
Both your suggestion and the one in json2.js fail to do that.
No, I don't think it will be that difficult, but I want to get a test
suite for it first. Either with what I have now or with JsUnit.
The type of setup I am working on uses object literal notation for the
tests. I use Java style annotations, but in the test name.
For example:
APE.test.testSimple({
'test JSON.parse("1.") @throws SyntaxError' : function() {
JSON.parse("1.");
}
});
That test function would be expected to throw and in this case, the
thrown object would have a `name` property of exactly "SyntaxError".
Assertions use N-Unit style constraints. It's a bigger project than for
just this JSON test and the TestReporter is not done. IT renders the
tree as a UL but doesn't show any results (pass, fail, ignore, etc).
JsUnit would work fine for a JSON test and I may just use that instead.
After some sleep.
Garrett