我们都知道可以使用JSON.parse()
将字符串'{"a":0,"b":"haha"}'
转换为对象{a: 0, b: 'haha'}
。
但是我们可以将字符串'{a: 0, b: "haha"}'
转换为对象{a: 0, b: 'haha'}
吗?
我正在编写一个Web搜寻器,我需要在页面中获取数据。但是完整的数据不是在DOM中,而是在一个<script>
元素中。因此,我在<script>
中获得了有用的内容,并将该字符串(如'window.Gbanners = [{...}, {...}, {...}, ...];'
)转换为类似JSON的字符串(如'{banners : [...]}'
)。但是,我无法解析“类似于JSON”的字符串。有没有人有办法解决吗?
类似的方法可能起作用:
function evalJsString(str) {
let a = null;
try {
eval('a = ' + str);
} catch (err) {
console.error(err);
}
if(typeof a === "object")
return a;
else
return null;
}
evalJsString('({a: 0, b: "haha"})');
{a: 0, b: "haha"}
之类的字符串不是JSON,而只是一堆JavaScript代码。
获取内部数据的JSON表示形式的最佳方法是通过JS解析器(例如Esprima)运行它,遍历语法树并从中构建一个json对象。这需要一些工作,但是至少您将正确解析并正确处理转义序列。
这里是起点:
const esprima = require("esprima");
const code = '({a: 0, b: "haha"})';
const ast = esprima.parse(code);
const properties = ast.body[0].expression.properties;
const output = properties.reduce((result, property) => {
result[property.key.name] = property.value.value;
return result;
}, {});
console.log(output);
此代码假设输入代码看起来很多-对于原型来说可能还不错,但仍然需要错误检查和处理嵌套对象。
((更通用的方法可能涉及采用ObjectExpression
并返回等效JSON的递归函数。)
我还必须将您的输入括在括号中,以便根据JS语法,它是一个表达式(不是块语句)。
由于eval()具有安全缺陷,最好不要使用它。一种可能的方法是创建一个自己的解析器,将其转换为JSON字符串,然后应用JSON.parse()。如下所示
function toJSONString(input) {
const keyMatcher = '([^",{}\\s]+?)';
const valMatcher = '(.,*)';
const matcher = new RegExp(`${keyMatcher}\\s*:\\s*${valMatcher}`, 'g');
const parser = (match, key, value) => `"${key}":${value}`
return input.replace(matcher, parser);
}
JSON.parse(toJSONString('{a: 0, b: "haha"}'))