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

时间:2010-11-17 23:10:47

标签: 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 );
}

5 个答案:

答案 0 :(得分:5)

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

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

答案 1 :(得分:1)

我认为让实际测试用例清除此实现的任何问题会很有帮助。我添加了一个名为JSOL的github项目,并进行了一些测试。请填写免费添加并找到问题。感谢。

https://github.com/daepark/JSOL

答案 2 :(得分:0)

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

希望这有帮助

答案 3 :(得分:0)

使用JSON5.parse

JSON5是JSON的超集,它支持ES5语法,包括未加引号的属性键。 JSON5参考实现(json5 npm package)提供了一个JSON5对象,该对象具有与内置JSON对象相同的方法,并且具有相同的参数和语义。

答案 4 :(得分:0)

“带注释的JSON”实际上是有效的javascript,因此在javascript环境中,解析它的最简单的本地方法就是像这样评估它

function evalJs(js) {
    let fn = new Function("return (" + js + ")"),
        res = fn()
    return res;
}

let json5 = "{\n" +
    "//////\n" +
    "key: 5," +
    "}"

let data = evalJs(json5)
console.info(data)

输出为

{ key: 5 }