JS:如何将字符串转换为JS对象(而不是JSON)?

5

我知道如何解析一个有效的JSON字符串:JSON.parse('{"key" : "value"}')

但对于一个有效的JS对象,但无效的JSON,例如:JSON.parse("{ key : 'value'}")? 上面的例子会抛出:

Uncaught SyntaxError: Unexpected token k in JSON at position 2

我的真正目标甚至更加棘手。我想将一个包含正则表达式(JSON不支持但JS支持)的JS对象字符串解析成JS对象:

'{ key1 : /val1/g , key2 : /val2/i }'

我最终希望将这个对象与Mongoose一起使用,并使用它查找文档:

Model.find({
     key1 : /val1/g ,
     key2 : /val2/i
})

我尝试对字符串应用了一个相当复杂的正则表达式,将/val1/g替换为new RegEx("val1","i")

str = str.replace( /\/(.+?)\/(g?i?).+?(?=,|})/g , "new RegExp(`$1`,`$2`)" )
< p > .replace() 操作能够按照我想要的方式修改字符串。它会产生以下结果:

{ key1 : new RegExp("val1","g") , key2 : new RegExp("val2","i") }

但是当我尝试使用JSON.parse解析它时,仍然失败,因为new RegEx("val1","i")不是一个有效的值。


4
我很讨厌自己说这句话,但也许 eval 是你要找的东西? - Emile Bergeron
谢谢,确实是这样,我没有考虑到。Eval太强大了 :) - Jeremy Thille
2个回答

10

如果你能控制并信任要转换的文本,你可以使用eval

var str = '{ key1 : /val1/g , key2 : /val2/i }';
var obj = eval("(" + str + ")");
console.log(obj.key1);

请注意,在执行eval时,由于您的表达式以{开头,您必须将其包装在()中,以便解析器知道这是开始一个对象初始化器,而不是一个块。

关于eval的一些注意事项:

  1. 它允许执行任意代码。因此,您必须真正信任您要eval的文本。不要eval用户输入。

  2. 直接包含对eval调用的执行上下文中的代码基本上无法优化,因为JavaScript引擎在解析代码时无法知道字符串将包含什么。因此,虽然我认为技术上这是过早的优化,但我建议将以上内容放在一个函数中,您从主逻辑中调用该函数,而不是直接嵌入主逻辑中。


1
那是一个很大的“如果”;-) - Joachim Sauer
1
@JoachimSauer:是的,我试图将其标记得相当大。 :-) 这个问题表明这里很可能是这种情况。 - T.J. Crowder
1
@EmileBergeron:啊,是的,值得提一下。我会这么做的。虽然不太可能出现问题,但还是要注意。 - T.J. Crowder
你不是一两周前已经以同样的方式回答了同样的问题吗?还是像我一样,越来越难找到旧的问题和答案,甚至是你自己写的? - user663031
说起来,我可以相信这个源并使用eval。这仅用于管理界面。谢谢T.J.,你让我的一天变得美好。(我将在6分钟内接受您的答案) - Jeremy Thille
显示剩余3条评论

1

我曾经遇到过类似的问题,并通过使用分割和缩减函数来解决它。

const getObjectFromString = (stringToParse) => {
    if(typeof stringToParse === 'string'){
        let currentKey = '';
        const keyValPairArr = stringToParse.replace('{','').replace('}','').split(':');
        return keyValPairArr.reduce((obj,current,index,arr)=>{
            const previousKey = currentKey;
            const arrKeyVal = current.trim().split(',');
            currentKey = index!==arr.length-1?arrKeyVal.pop().trim():'';
            const previousVal = arrKeyVal.join(',');
            if(previousKey&&previousVal!=='')obj[previousKey]=previousVal;
            return obj;
        },{})
    }else{
        return stringToParse||{};
    }
}

// following are some results

const example1 = getObjectFromString('{first : 1, second : 2nd, third: "third, 3rd" }')
console.log(example1) // output: {first: '1', second: '2nd', third: '"third, 3rd"'}

它会返回空对象或从传递的字符串转换而来的对象。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接