繁体   English   中英

使用来自JSON对象的数组表示法进行多级属性检索

[英]Multiple level attribute retrieval using array notation from a JSON object

我在这里遇到了一个精神上有问题的问题,我在Backbone中使用一个集合检索了一个JSON对象。 这是对象的样子:

{
    "MatchID": "00000001",
    "Date": "1970-01-01T00:00:00.000Z",
    "OriginalID": "",
    "Stage": {
        "StageNumber": "0",
        "StageType": "Stage Type"
    },
    "Round": {
        "RoundNumber": "0",
        "Name": "Round Name"
    },
    "Leg": "1",
    "HomeTeam": {
        "TeamID": "0",
        "Name": "Home Team Name"
    },
    "AwayTeam": {
        "TeamID": "0",
        "Name": "Away Team Name"
    },
    "Venue": {
        "VenueID": "0",
        "Name": "Venu Name"
    },
    "Referee": null,
}

我想对这些数据做什么,是根据特定属性过滤它,例如Venue.Name或Date属性(对象的深度不同,对于其他一些数据可能比两个级别更深) 。 我在Backbone集合中有以下代码来过滤并返回一个新集合,其中包含适当过滤的内容:

findWhere: function (Attribute, Value)
{
    return new Project.Collections.Fixtures(this.filter(function (fixture)
    {
        return eval('fixture.attributes.' + Attribute) == Value;
    }));
}

这允许我在属性中指定对于任何深度的对象,我想要过滤哪个属性,以及我希望它等于什么。 问题是,我真的不想使用“eval”来做这件事,但显然我不能将“[Attribute]”用于像“AwayTeam.TeamID”这样的东西,因为它不起作用。

有没有人知道我可以用来实现这个功能而不使用eval的方法?

这样的东西可以让你遍历对象的层次结构来找到一个值:

var x = {
    y: {
        z: 1
    }
};

function findprop(obj, path) {
    var args = path.split('.'), i, l;

    for (i=0, l=args.length; i<l; i++) {
        if (!obj.hasOwnProperty(args[i]))
            return;
        obj = obj[args[i]];
    }

    return obj;
}

findprop(x, 'y.z');

您可以将此作为方法添加到Fixture对象:

Fixture = Backbone.Model.extend({
    findprop: function(path) {
        var obj = this.attributes,
            args = path.split('.'), 
            i, l;

        for (i=0, l=args.length; i<l; i++) {
            if (!obj.hasOwnProperty(args[i]))
                return;
            obj = obj[ args[i] ];
        }
        return obj;
    }
});

并用它来提取价值

var f = new Fixture();
f.findprop("HomeTeam.TeamID");

然后可以将findWhere方法重写为

findWhere: function (Attribute, Value)
{
    return new Project.Collections.Fixtures(this.filter(function (fixture){
        return fixture.findprop(Attribute) === Value;
    }));
}

http://jsfiddle.net/nikoshr/wjWVJ/3/一起玩的小提琴

JavaScript对象中的属性可以通过方括号,字符串标识符以及标准点表示法来访问。

换句话说,这个:

fixture.attributes.something

与此相同:

fixture.attributes["something"]

您还可以将变量名称传递到方括号中,变量的值用作要检索的键。

因此,您可以将代码更改为:

findWhere: function (Attribute, Value)
{
    return new Project.Collections.Fixtures(this.filter(function (fixture)
    {
        return fixture.attributes[Attribute] === Value;
    }));
}

正如您在注释中指出的那样,这只处理一个级别的对象和属性。 要获取嵌套属性,您需要拆分“属性”变量并循环遍历各个部分。 我喜欢@ nikoshr的解决方案。

我拿了nikoshr的答案,并为它添加了一些递归的天赋:

  var findprop = function (obj, path) {
        var args = (typeof path === 'string') ? path.split('.') : path,
            thisProperty = obj[args[0]];
        if (thisProperty === undefined) { return; } //not found

        args.splice(0, 1); //pop this off the array

        if (args.length > 0) { return findprop(thisProperty, args); } //recurse
        else {return thisProperty; }
    };

我不确定递归cpu周期是否有很多好处,但我喜欢它们适当时的递归函数

那么使用eval()如下:

 var myObject = { first: 'Some', last: 'Person', address: { city: 'Melbourne', country: 'Australia' } } var propPath = 'address.city'; var city = eval("myObject."+propPath); console.log(city); // = Melbourne 

暂无
暂无

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

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