os0xさんにjson2.jsで使われている手法である事を教えてもらいました。
正しくはエスケープが必要。
以下フォーラムで議論されている内容から拝借
validating json unnecessarily is killing firefox - jQuery Forumこの検証手順は
// Try to use the native JSON parser first
http://forum.jquery.com/topic/validating-json-unnecessarily-is-killing-firefox
if (window.JSON && window.JSON.parse) {
try {
return window.JSON.parse( data );
} catch (err) {
jQuery.error( "Invalid JSON: " + data );
}
} else {
if ( /^[\],:{}\s]*$/.test(data.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, "@")
.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, "]")
.replace(/(?:^|:|,)(?:\s*\[)+/g, "")) ) {
return (new Function("return " + data))();
} else {
jQuery.error( "Invalid JSON: " + data );
}
- 使用可能な制御文字および改行を文字参照を"@"に置き換え
- 文字列と定数を"["に置き換え
- 全ての空白を削除
^[\],:{}\s]*$
という正規表現で表す事が出来るという物。何個か試してみましたが、100%完璧な検証というよりも簡易的な物みたい。でも不正なスクリプト除けには使えそうな感じ。要検証
最近私が書くvimscriptではeval()を使ってJSONをパースさせてる物があるので、使えないかと思いサクっとvimscriptに移植してみた。
function! s:ValidateJSON(str)
let str = a:str
let str = substitute(str, '\\\%(["\\\/bfnrt]\|u[0-9a-fA-F]\{4}\)', '\@', 'g')
let str = substitute(str, '"[^\"\\\n\r]*\"\|true\|false\|null\|-\?\d\+\%(\.\d*\)\?\%([eE][+\-]\?\d\+\)\?', ']', 'g')
let str = substitute(str, '\%(^\|:\|,\)\%(\s*\[\)\+', '', 'g')
return str =~ '^[\],:{} \t\n]*$'
endfunction
let json = substitute(join(readfile(expand('<sfile>')), "\n"), '.*\nfinish\n', '', '')
if s:ValidateJSON(json)
echo "is valid json"
else
echo "is invalid json"
endif
finish
{
"testID": "2",
"testResults": [
{
"testResultID": "2",
"contactID": "1",
"answers": [
{
"questionID": "6",
"answer": "A",
"num_attempts": "1",
},
{
"questionID": "7",
"answer": "I do not know.",
"num_attempts": "0",
},
{
"questionID": "9",
"answer": "blah",
"num_attempts": "0",
}
]
},
{
"testResultID": "4",
"contactID": "231",
"answers": [
]
},
{
"testResultID": "5",
"contactID": "231",
"answers": [
{
"questionID": "6",
"answer": "d",
"num_attempts": "1",
},
{
"questionID": "7",
"answer": "hello.",
"num_attempts": "1",
},
{
"questionID": "9",
"answer": "This is just test posted text.",
"num_attempts": "1",
}
]
}
]
}
サンプルでもvalidが出てる。明日にでもeval()使ってるvimscriptに入れていこう。
こういう記事書くと、勝手に検証してくれる人がいて、最近はありがたい世の中になったもんだ...と勝手に期待。