如何将类似JSON(不是JSON)的字符串转换为对象?

时间:2018-03-05 14:09:32

标签: javascript json

我们都知道我们可以使用JSON.parse()将字符串'{"a":0,"b":"haha"}'转换为对象{a: 0, b: 'haha'}

但是我们可以将字符串'{a: 0, b: "haha"}'转换为对象{a: 0, b: 'haha'}吗?

我正在编写一个网络抓取工具,我需要在页面中获取数据。但是完整的数据不在DOM中,而是在一个<script>元素中。所以我在<script>中获得了有用的内容,并将该字符串(如'window.Gbanners = [{...}, {...}, {...}, ...];')转换为类似JSON的字符串(如'{banners : [...]}')。但是,我无法解析“类JSON”字符串。有没有人有办法解决吗?

3 个答案:

答案 0 :(得分:7)

{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语法,我还必须将您的输入包装在括号中,以便它是一个表达式(而不是块语句)。

答案 1 :(得分:2)

这样的事可能有用:

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"})');

答案 2 :(得分:0)

由于 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"}'))