JS:将字符串“foo [bar]”转换为代码obj.foo.bar的简单方法?

时间:2012-06-16 02:20:16

标签: javascript node.js

我的变量obj定义如下:

{user: {username: "AzureDiamond", password: "hunter2"}}

我有一个字符串str,可以定义为以下任何字符串:

  • “用户”
  • “用户[用户名]”
  • “用户[口令]”
  • “假”

JS(特别是node.js)中有一种相对简单的方法可以基本上/动态地执行以下操作吗?

  • str == "user"时,请返回{username: "AzureDiamon", password: "hunter2"}
  • str == "user[username]"时,返回“AzureDiamond”
  • str == "user[password]"时,返回“hunter2”
  • str == "fake"时,请返回null

编辑:这个问题更多的是要找出是否有更容易的东西或构建到JS / node.js中,除了正则表达式匹配之外我还可以使用。

3 个答案:

答案 0 :(得分:4)

解决方案

如果您确定str的语法正确,则该函数可能如下所示:

function get_by_path(source, path){
    var path_elements = path.split(']').join('').split('[');
    for (var i=0; i < path_elements.length; i++){
        source = source[path_elements[i]];
        if (typeof source === 'undefined'){
            return null;
        }
    };
    return source;
};

测试

这就是它的表现:

var data = {'user': {
    'username': "AzureDiamond", 'password': "hunter2",
    'details': {'address': {'street': "Happiness Street"}}
}};

get_by_path(data, 'user');                           // gives user object
get_by_path(data, 'user[username]');                 // gives "hunter2"
get_by_path(data, 'user[password]');                 // gives "AzureDiamond"
get_by_path(data, 'fake');                           // gives null
get_by_path(data, 'user[details][address][street]'); // gives "Happiness Street"

说明

在脚本不使用正则表达式,也没有危险eval()电话,只假定你的“路径的”将用一个字就没有支架和每一个部分(如果有的话)会括在方括号内的单词。如果在遍历的对象中找不到某个路径,则将返回null。如果找到它,它将被返回(无论它是否是一些复杂的对象,字符串,null,布尔或其他任何东西)。

脚本从解析您的路径开始。它通过删除右方括号(“]”)并通过打开方括号(“[”)拆分结果字符串来实现。这个过程如下:

"user"                  -> "user"                -> ["user"]
"user[username]"        -> "user[username"       -> ["user", "username"]
"user[password]"        -> "user[password"       -> ["user", "password"]
"user[address][street]" -> "user[address[street" -> ["user", "address", "street"]
"fake"                  -> "fake"                -> ["fake"]

因此,如您所见,最后您有一个路径元素数组。这些是逐个评估的。如果在任何级别都不能使适当的步骤更深入到数据参数的结构中,则返回null。否则返回最后访问的元素。

证明

证明它有效:http://jsfiddle.net/EJCgE/2/

编辑:由于字符串replace()方法的工作原理,更复杂的路径(当有两个以上的级别时)存在一些问题。我已将代码更新为不包含jQuery并修复该问题。

EDIT2 :我已更新脚本以删除冗余行和一个冗余变量。

答案 1 :(得分:2)

这是直接从EXTJS3源代码中获取的,但我已多次使用它来做类似的事情。

createAccessor : function(){
    var re = /[\[\.]/;
    return function(expr) {
        if(Ext.isEmpty(expr)){
            return Ext.emptyFn;
        }
        if(Ext.isFunction(expr)){
            return expr;
        }
        var i = String(expr).search(re);
        if(i >= 0){
            return new Function('obj', 'return obj' + (i > 0 ? '.' : '') + expr);
        }
        return function(obj){
            return obj[expr];
        };

    };
}(),

你会像这样使用它:

var accessor = createAccessor(str);
var data = accessor(object);

答案 2 :(得分:0)

尝试使用eval功能。它需要一个字符串,并执行该字符串,就像它是javascript代码一样。例如:

var data = {user: {username: "AzureDiamond", password: "hunter2"}};
var str = "user[\"password\"]";
console.log( eval("data." + str) );
// Prints "hunter2"

你必须非常小心,因为根据str来自哪里,人们基本上可以远程地在你的服务器上运行代码。在执行之前使用正则表达式验证字符串,以确保人们无法向您发送偷偷摸摸的信息并将您的服务器破解为位。

编辑:请注意,您还必须引用password,以便在执行时将其视为字符串,而不是变量。