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

前端 未结 3 945
独厮守ぢ
独厮守ぢ 2021-01-24 12:50

We all know we can use JSON.parse() to convert the string \'{\"a\":0,\"b\":\"haha\"}\' to the object {a: 0, b: \'haha\'}.

But can

相关标签:
3条回答
  • 2021-01-24 13:32

    A string like {a: 0, b: "haha"} is not JSON, but just a bunch of JavaScript code.

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

    I also had to wrap your input in parentheses so that it's an expression (not a block statement) according to JS grammar.

    0 讨论(0)
  • 2021-01-24 13:44

    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"})');
    
    0 讨论(0)
  • 2021-01-24 13:48

    As eval() has security flaws, it's better not to use it. A possible way would be creating a own parser to convert it to JSON string and then apply 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"}'))
    
    0 讨论(0)
提交回复
热议问题