【问题标题】:JSON.stringify whitelisting with nested objectsJSON.stringify 白名单与嵌套对象
【发布时间】:2013-07-04 15:00:01
【问题描述】:

举个例子:

var test = {
    "company_name": "Foobar",
    "example": "HelloWorld",
    "address": {
        "street": "My Street 12",
        "example": "BarFoo",
        "details": "Berlin",
    }
}

console.log(JSON.stringify(test, ['company_name','address','street','example']));

// What I actually want
// console.log(JSON.stringify(test, ['company_name','address.street','address.example']));

如何使用 JSON 的 stringify 函数正确处理嵌套对象?

由于我有巨大的 JSON 对象,因此嵌套对象的键与其“父”对象相同。我想更详细地指定我的白名单。

【问题讨论】:

    标签: javascript json whitelist


    【解决方案1】:

    您可以在庞大的 JSON 对象中添加 toJSON 方法:

    var test = {
        "company_name": "Foobar",
        "example": "HelloWorld",
        "address": {
            "street": "My Street 12",
            "example": "BarFoo",
            "details": "Berlin",
        },
        toJSON: function () {
            return {
                company_name: this.company_name,
                address: {
                    street: this.address.street,
                    example: this.address.example
                }
            }
        }
    }
    

    然后,你会得到:

    console.log(JSON.stringify(test)); // "{"company_name":"Foobar","address":{"street":"My Street 12","example":"BarFoo"}}"
    

    或者,您可以使用一些过滤功能:(此功能使用 lodash)

    function filter(object, keys, sep) {
        sep = sep || '.';
        var result = {};
        _.each(keys, function (key) {
            var keyParts = key.split(sep),
                res = object, 
                branch = {},
                branchPart = branch;
    
            for (var i = 0; i < keyParts.length; i++) {
                key = keyParts[i];
                if (!_.has(res, key)) {
                    return;
                }
    
                branchPart[key] = _.isObject(res[key]) ? {} : res[key];
    
                branchPart = branchPart[key];
                res = res[key];
            }
    
            _.merge(result, branch);
        });
        return result;    
    }
    console.log(JSON.stringify(filter(test, ['company_name', 'address.street', 'address.example']))); // "{"company_name":"Foobar","address":{"street":"My Street 12","example":"BarFoo"}}"
    

    查看 jsfiddle http://jsfiddle.net/SaKhG/

    【讨论】:

    • 不幸的是,这对我来说不是一个解决方案,因为白名单是基于上下文的(并且 JSON 对象实际上是转换的猫鼬对象)。
    • 还有另一种解决方案,现在我在jsfiddle中测试它。我会在几分钟内添加它。
    • 更新了我的答案,但为时已晚:)
    【解决方案2】:

    如果您愿意努力加入白名单,那么您可以建立一个有效键数组,它可以提供类似于多少系统进行 JSON 嵌套的能力(. 分隔符,或任何您选择的分隔符)。

    var whitelistedObj = whitelistJson(obj, ["company_name", "example", "address.street", "address.example"]);
    
    function whitelistJson(obj, whitelist, separator) {
        var object = {};
    
        for (var i = 0, length = whitelist.length; i < length; ++i) {
            var k = 0,
                names = whitelist[i].split(separator || '.'),
                value = obj,
                name,
                count = names.length - 1,
                ref = object,
                exists = true;
    
            // fill in any empty objects from first name to end without
            //  picking up neighboring fields
            while (k < count) { // walks to n - 1
                name = names[k++];
                value = value[name];
    
                if (typeof value !== 'undefined') {
                    if (typeof object[name] === 'undefined') {
                        ref[name] = {};
                    }
    
                    ref = ref[name];
                }
                else {
                    exists = false;
                    break;
                }
            }
    
            if (exists) {
                ref[names[count]] = value[names[count]];
            }
        }
    
        return object;
    }
    

    我有一个 JSFiddle 也显示了它的用法(以确保它确实适用于我公认的小样本集)。

    【讨论】:

    • 太棒了!您缺少返回对象。如果我相应地更改它,它会按预期工作。还是我混淆了什么?
    • @ChristopherWill 不会混淆任何东西。我忘了从 JS Fiddle 示例中复制回来。唯一需要注意的是它与您想要的功能略有不同,因为您必须明确命名每个属性名称(例如,"example""address.example")。这是一个更严格的白名单,但更容易实施。
    • 我真的很喜欢这种方法,这正是我正在寻找的。​​span>
    猜你喜欢
    • 2013-11-07
    • 2014-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-19
    • 1970-01-01
    • 1970-01-01
    • 2014-09-13
    相关资源
    最近更新 更多