简体   繁体   English

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

[英]How to convert a JSON-like (not JSON) string to an object?

We all know we can use JSON.parse() to convert the string '{"a":0,"b":"haha"}' to the object {a: 0, b: 'haha'} .我们都知道我们可以使用JSON.parse()将字符串'{"a":0,"b":"haha"}'转换为对象{a: 0, b: 'haha'}

But can we convert the string '{a: 0, b: "haha"}' to the object {a: 0, b: 'haha'} ?但是我们可以将字符串'{a: 0, b: "haha"}'转换为对象{a: 0, b: 'haha'}吗?

I'm writing a web crawler and I need to get the data in the page.我正在写一个网络爬虫,我需要获取页面中的数据。 But the complete data is not in DOM but in one <script> element.但是完整的数据不在 DOM 中,而是在一个<script>元素中。 So I got the useful content in the <script> and converted that string (like 'window.Gbanners = [{...}, {...}, {...}, ...];' ) to a JSON-like string (like '{banners: [...]}' ).所以我在<script>中获得了有用的内容并将该字符串(如'window.Gbanners = [{...}, {...}, {...}, ...];' )转换为类似 JSON 的字符串(如'{banners: [...]}' )。 However, I couldn't parse the "JSON-like" string.但是,我无法解析“类似 JSON”的字符串。 Does anyone have a solution?有没有人有办法解决吗?

A string like {a: 0, b: "haha"} is not JSON, but just a bunch of JavaScript code.{a: 0, b: "haha"}这样的字符串不是 JSON,而是一堆 JavaScript 代码。

Best way to get a JSON representation of data inside is to run it through a JS parser (such as Esprima ), traverse the syntax tree and build a json object out of it.获取内部数据的 JSON 表示的最佳方法是通过 JS 解析器(例如Esprima )运行它,遍历语法树并从中构建一个 json 对象。 This needs some work, but at least you'll have the parsing done correctly, with proper handling of escape sequences.这需要一些工作,但至少您可以正确地完成解析,并正确处理转义序列。

Here's a starting point:这是一个起点:

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);

This code assumes a lot about what the input code looks like - might be OK for a prototype, but still needs error checking and handling nested objects.这段代码假设了很多关于输入代码的样子——对于原型来说可能没问题,但仍然需要错误检查和处理嵌套对象。

(A more generic approach could involve a recursive function that takes an ObjectExpression and returns an equivalent JSON.) (更通用的方法可能涉及一个递归函数,该函数采用ObjectExpression并返回等效的 JSON。)

I also had to wrap your input in parentheses so that it's an expression (not a block statement) according to JS grammar.我还必须将您的输入括在括号中,以便根据 JS 语法它是一个表达式(而不是块语句)。

Something like this might work:这样的事情可能会起作用:

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

As eval() has security flaws, it's better not to use it.由于eval()存在安全漏洞,最好不要使用它。 A possible way would be creating a own parser to convert it to JSON string and then apply JSON.parse() .一种可能的方法是创建自己的解析器以将其转换为 JSON 字符串,然后应用JSON.parse() Something like below像下面这样的东西

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM