如何将带有数组的字符串转换为数组

11

我该如何将这个响应转换为有效的数组?
我想在数据上执行Object.map

var user_roles = "['store_owner', 'super_admin']";

这不是一个有效的 JSON,所以我无法使用 JSON.parse


2
你如何生成这个字符串?也许一个符合 JSON 标准的字符串更容易解析。 - Nina Scholz
1
虽然这个字符串无法被解析为 JSON,但它是有效的 JS。也许你可以使用 eval - Berry M.
1
没错,eval 能用,但这只是一个变通方法。最好生成一个没有自定义格式的字符串。 - Nina Scholz
1
这不是那个问题的副本,因为它不是有效的JSON。 - Adelin
3个回答

8

大多数在这里发布的答案建议使用JSON.parse,然后在被删除之前被踩了3次。人们在这里忽视的是缺乏符合JSON规范的引号。然而,该字符串是有效的JavaScript。您可以执行以下操作:

const obj = {
  thing: "['store_owner', 'super_admin']",
  otherThing: "['apple', 'cookies']"
}

for (const key in obj) {
  const value = obj[key];
  obj[key] = eval(value);
}

console.log(obj);

输出将是一个有效的 JavaScript 对象:

{"thing":["store_owner","super_admin"],"otherThing":["apple","cookies"]} 

注意使用eval()!但是,要关注它的安全性问题。 JavaScript eval()和安全性

你可以在这里尝试:https://es6console.com/jjqvrnhg/


因此我添加了安全警告。整个情况都有点不妙! - Berry M.
1
@ZakariaAcharki 是的,是的...你只是在已经提到的安全问题上添加噪音(Berry链接了一个类似的问题)...相反的解决方案会更有用。 - CPHPython
3
即使有警告提示,也不应考虑使用eval()。根据原帖的描述,输入内容明显不受其控制。这些警告具体适用于这种情况。 - Mark
1
只要字符串中不包含转义的单引号,它就能正常工作: "['store_owner', 'super_admin\'s right']" - Guillaume Georges
1
我同意,@MarkMeyer。在这种情况下,最好的解决方案当然是重新考虑导致这种情况的整个设置。你永远不会覆盖所有边缘情况,比如Guillaume的情况。 - Berry M.
显示剩余2条评论

3
我使用了在这里找到的JSON.parse polyfill。
而且,我将字符串的含义替换为由单引号''组成的表示法

/*
    json_parse.js
    2016-05-02
    Public Domain.
    NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
    This file creates a json_parse function.
        json_parse(text, reviver)
            This method parses a JSON text to produce an object or array.
            It can throw a SyntaxError exception.
            The optional reviver parameter is a function that can filter and
            transform the results. It receives each of the keys and values,
            and its return value is used instead of the original value.
            If it returns what it received, then the structure is not modified.
            If it returns undefined then the member is deleted.
            Example:
            // Parse the text. Values that look like ISO date strings will
            // be converted to Date objects.
            myData = json_parse(text, function (key, value) {
                var a;
                if (typeof value === "string") {
                    a =
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
                    if (a) {
                        return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
                            +a[5], +a[6]));
                    }
                }
                return value;
            });
    This is a reference implementation. You are free to copy, modify, or
    redistribute.
    This code should be minified before deployment.
    See http://javascript.crockford.com/jsmin.html
    USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
    NOT CONTROL.
*/

/*jslint for */

/*property
    at, b, call, charAt, f, fromCharCode, hasOwnProperty, message, n, name,
    prototype, push, r, t, text
*/

var json_parse = (function () {
    "use strict";

// This is a function that can parse a JSON text, producing a JavaScript
// data structure. It is a simple, recursive descent parser. It does not use
// eval or regular expressions, so it can be used as a model for implementing
// a JSON parser in other languages.

// We are defining the function inside of another function to avoid creating
// global variables.

    var at;     // The index of the current character
    var ch;     // The current character
    var escapee = {
        "\"": "\"",
        "\\": "\\",
        "/": "/",
        b: "\b",
        f: "\f",
        n: "\n",
        r: "\r",
        t: "\t"
    };
    var text;

    var error = function (m) {

// Call error when something is wrong.

        throw {
            name: "SyntaxError",
            message: m,
            at: at,
            text: text
        };
    };

    var next = function (c) {

// If a c parameter is provided, verify that it matches the current character.

        if (c && c !== ch) {
            error("Expected '" + c + "' instead of '" + ch + "'");
        }

// Get the next character. When there are no more characters,
// return the empty string.

        ch = text.charAt(at);
        at += 1;
        return ch;
    };

    var number = function () {

// Parse a number value.

        var value;
        var string = "";

        if (ch === "-") {
            string = "-";
            next("-");
        }
        while (ch >= "0" && ch <= "9") {
            string += ch;
            next();
        }
        if (ch === ".") {
            string += ".";
            while (next() && ch >= "0" && ch <= "9") {
                string += ch;
            }
        }
        if (ch === "e" || ch === "E") {
            string += ch;
            next();
            if (ch === "-" || ch === "+") {
                string += ch;
                next();
            }
            while (ch >= "0" && ch <= "9") {
                string += ch;
                next();
            }
        }
        value = +string;
        if (!isFinite(value)) {
            error("Bad number");
        } else {
            return value;
        }
    };

    var string = function () {

// Parse a string value.

        var hex;
        var i;
        var value = "";
        var uffff;

// When parsing for string values, we must look for " and \ characters.

        if (ch === "\'") {
            while (next()) {
                if (ch === "\'") {
                    next();
                    return value;
                }
                if (ch === "\\") {
                    next();
                    if (ch === "u") {
                        uffff = 0;
                        for (i = 0; i < 4; i += 1) {
                            hex = parseInt(next(), 16);
                            if (!isFinite(hex)) {
                                break;
                            }
                            uffff = uffff * 16 + hex;
                        }
                        value += String.fromCharCode(uffff);
                    } else if (typeof escapee[ch] === "string") {
                        value += escapee[ch];
                    } else {
                        break;
                    }
                } else {
                    value += ch;
                }
            }
        }
        error("Bad string");
    };

    var white = function () {

// Skip whitespace.

        while (ch && ch <= " ") {
            next();
        }
    };

    var word = function () {

// true, false, or null.

        switch (ch) {
        case "t":
            next("t");
            next("r");
            next("u");
            next("e");
            return true;
        case "f":
            next("f");
            next("a");
            next("l");
            next("s");
            next("e");
            return false;
        case "n":
            next("n");
            next("u");
            next("l");
            next("l");
            return null;
        }
        error("Unexpected '" + ch + "'");
    };

    var value;  // Place holder for the value function.

    var array = function () {

// Parse an array value.

        var arr = [];

        if (ch === "[") {
            next("[");
            white();
            if (ch === "]") {
                next("]");
                return arr;   // empty array
            }
            while (ch) {
                arr.push(value());
                white();
                if (ch === "]") {
                    next("]");
                    return arr;
                }
                next(",");
                white();
            }
        }
        error("Bad array");
    };

    var object = function () {

// Parse an object value.

        var key;
        var obj = {};

        if (ch === "{") {
            next("{");
            white();
            if (ch === "}") {
                next("}");
                return obj;   // empty object
            }
            while (ch) {
                key = string();
                white();
                next(":");
                if (Object.hasOwnProperty.call(obj, key)) {
                    error("Duplicate key '" + key + "'");
                }
                obj[key] = value();
                white();
                if (ch === "}") {
                    next("}");
                    return obj;
                }
                next(",");
                white();
            }
        }
        error("Bad object");
    };

    value = function () {

// Parse a JSON value. It could be an object, an array, a string, a number,
// or a word.

        white();
        switch (ch) {
        case "{":
            return object();
        case "[":
            return array();
        case "\'":
            return string();
        case "-":
            return number();
        default:
            return (ch >= "0" && ch <= "9")
                ? number()
                : word();
        }
    };

// Return the json_parse function. It will have access to all of the above
// functions and variables.

    return function (source, reviver) {
        var result;

        text = source;
        at = 0;
        ch = " ";
        result = value();
        white();
        if (ch) {
            error("Syntax error");
        }

// If there is a reviver function, we recursively walk the new structure,
// passing each name/value pair to the reviver function for possible
// transformation, starting with a temporary root object that holds the result
// in an empty key. If there is not a reviver function, we simply return the
// result.

        return (typeof reviver === "function")
            ? (function walk(holder, key) {
                var k;
                var v;
                var val = holder[key];
                if (val && typeof val === "object") {
                    for (k in val) {
                        if (Object.prototype.hasOwnProperty.call(val, k)) {
                            v = walk(val, k);
                            if (v !== undefined) {
                                val[k] = v;
                            } else {
                                delete val[k];
                            }
                        }
                    }
                }
                return reviver.call(holder, key, val);
            }({"": result}, ""))
            : result;
    };
}());

console.log(json_parse("['store_owner', 'super_admin']"));


-2

使其符合JSON规范

JSON.parse(user_roles.replace(/(?<!\\)'/g,'"')

这个方法通过修复代码无法被 JSON 解析的原因来实现。原因在于 JSON 不允许使用单引号 ('),所以我们把它们改成了双引号 (")

编辑:

我已经修改了代码,使得当 ' 前面有一个\时,它不会被替换为 "


str = "['store_owner', 'super_ad\'min']", JSON.parse(str.replace(/'/g,'"')) => unexpected token m - Adelin
这似乎不是原帖作者可能遇到的问题,但我已经做了处理,以防万一,它仍然可以正常工作。 - Andria
我仍然得到完全相同的错误。 - Adelin
@Adelin 在字符串中,它必须以“\”为前缀,只是放置“'”会返回“'”,你需要“\'”。 - Andria
1
我认为这是目前最好的解决方案... - Zakaria Acharki

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接