使用不带引号的键安全地解析JSON字符串

dae*_*ark 16 javascript json object-literal

json2.js严格要求所有对象键都是双引号.但是,在Javascript语法{"foo":"bar"}中相当于{foo:"bar"}.

我有一个textarea接受来自用户的JSON输入,并希望"轻松"双重引用键的限制.我已经看过json2.js如何在它出现之前的四个阶段验证JSON字符串.我能够添加第5个阶段以允许不带引号的密钥,并想知道这个逻辑是否存在任何安全隐患.

var data = '{name:"hello", age:"23"}';

// Make sure the incoming data is actual JSON
// Logic borrowed from http://json.org/json2.js
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, ":") // EDITED: allow key:[array] by replacing with safe char ":"
     /** everything up to this point is json2.js **/

     /** this is the 5th stage where it accepts unquoted keys **/         
     .replace(/\w+\s*\:/g, ":")) ) { // EDITED: allow any alphanumeric key

  console.log( (new Function("return " + data))() );
}
else {
  throw( "Invalid JSON: " + data );
}
Run Code Online (Sandbox Code Playgroud)

Ant*_*lli 6

data.replace(/(['"])?([a-zA-Z0-9]+)(['"])?:/g, '"$2":');
Run Code Online (Sandbox Code Playgroud)

这将替换参数名称上的任何单引号,并添加任何缺少的引号.

  • 这似乎有效.除非您未能处理下划线.这是一个更新的正则表达式:`hash.replace(/(['"])?([a-zA-Z0-9 _] +)(['"])?:/ g,'"$ 2":');` (7认同)
  • 这个答案远非完美.试试`{a:['b','c']}`或`{a:"注意:发生了什么."} (4认同)
  • 请注意,尽管此正则表达式可以在某些非常特殊的情况下使用,但它不能**工作于更复杂的内容,例如:`{location:'http://www.google.com'}`,但您最终会得到无效的JSON:`{“ location”:“ http”://www.google.com'}` (2认同)

mat*_*sta 1

JSON 不允许不带引号的键。JSON 是 JavaScript 表示法的子集,不包括不带引号的键。将不带引号的键传递给几乎任何 JSON 解析器都可能会抛出错误或返回“意外”结果。

希望这可以帮助

  • 当然,对于 JSON 来说确实如此,但 JavaScript 确实允许在对象字面量中使用不带引号的键。这只是有点问题,因为您不能使用破折号或不带引号的保留字。不过,我认为提问者已经知道这一点了。 (4认同)