将 JavaScript 对象字面量转换为不带“eval”的 JavaScript 对象

Fr3*_*Dev 5 javascript

我正在制作一个网络爬虫,网页上的大部分数据都是 JavaScript 对象文字形式,例如:

// Silly example
var user = {
    name: 'John', 
    surname: 'Doe',
    age: 21,
    family: [
        {
            name: 'Jane',
            surname: 'Doe',
            age: 37
        },
        // ...
    ]
};
Run Code Online (Sandbox Code Playgroud)

因此,当我在 JavaScript 应用程序中搜索内容时,上面的对象将是:

"{name: 'John', surname: 'Doe', age: 21, family: [{name: 'Jane', surname: 'Doe', age: 37}]}"
Run Code Online (Sandbox Code Playgroud)

是否可以在不使用“eval”或创建自己的解析器的情况下将它们解析为常规 JavaScript 对象?我看到了其他类似的问题,但答案不适用:它们都建议JSON.parse()(不适用)和eval(出于安全原因我不能使用它)。例如,在这个问题中,所有答案都暗示evalnew Function()基本相同。

如果没有其他方法,将文字转换为正确的 JSON 然后将其解析为 JavaScript 对象是一个可行的选择吗?

这就是我现在尝试的,它适用于一个简单的对象,但我不确定它是否适用于任何地方:

const literal = script.innerText.slice(script.innerText.indexOf('{'), script.innerText.lastIndexOf('}') + 1);
const json = literal.replace(/.*:.*(\".*\"|\'.*\'|\[.*\]|\{.*\}|true|false|[0-9]+).*,/g, (prev) => {
  let parts = prev.split(':');
  let key = '"' + parts.shift().trim() + '"';
  let value = parts.join(':').replace(/'.*'/, (a) => {
    return '"' + a.slice(1, a.length - 1) + '"';
  }).trim();
  return key + ':' + value;
});
const obj = JSON.parse(json);
Run Code Online (Sandbox Code Playgroud)

Tom*_*m M 1

假设您使用节点,一个简单的解决方法是

// scraper.js
const fs = require('fs');
const objectString = myScraper.scrape('example.com');

fs.writeFileSync('./scraped.js', objectString);

// myAppUsingTheData.js
const myObj = require('myAppUsingTheData');
Run Code Online (Sandbox Code Playgroud)

然而,require 仍然以某种方式涉及评估。并且您需要单独的进程才能访问您的对象。另外,您需要以某种方式插入module.exports. 如果您只想解析对象,请尝试JSON5

const myObj = JSON5.parse(objectString);
console.log(myObj.name)
Run Code Online (Sandbox Code Playgroud)

使用 JSON5 将有效防止您运行不是应用程序中的对象并且显然可以解析未加引号的 JSON 键的恶意代码。