0

我有一个 JavaScript 对象,我正在使用 JSON.stringify 对其进行字符串化,该对象返回一个带有父子数据的 JSON 字符串。

当我尝试将此字符串解析回对象时,子对象现在为空。

function cacheForm(agency) {

 var agency = ko.toJS(this); //easy way to get a clean copy
 delete agency.contacts; //remove an extra property

        for (i in agency.offices) {
            for (val in agency.offices[i]) {
                //delete agency.offices[i].agency;
                //delete agency.offices[i].agencyID;
            }
        }

            for (i in agency.offices) {
                for (ii in agency.offices[i].contacts) {
                    for (val in agency.offices[i].contacts[ii]) {
                        //delete agency.offices[i].contacts[ii].office;
                        //delete agency.offices[i].contacts[ii].agencyID;
                        //delete agency.offices[i].contacts[ii].officeID;
                    }
                }
            }

                 var value = agency;

                 var cache = [];
                 parsed = JSON.stringify(value, function (key, value) {
                     if (typeof value === 'object' && value !== null) {
                         if (cache.indexOf(value) !== -1) {
                             // Circular reference found, discard key
                             return;
                         }
                         // Store value in our collection
                         cache.push(value); 
                     }

                     return value;
                 });


                 var data = JSON.parse(parsed);
    }

编辑

我正在传递给我的 cacheForm 函数并正在使用的视图模型的代理部分

 var agency = ko.toJS(this); 

让我的数据在可以解析为 JSON 字符串的对象中可用。我可能会在我的帖子中删除此代码,因为我的原始代码有很多注释。

我在 stringify 之前的代理对象 - 它有子数据

4

3 回答 3

3

您的问题最初显示了data.offices = [null]突出显示的屏幕截图。

这不是解析错误,而是stringify. 你的粘贴已经有了data.offices = [null]

MDN指出replacer

注意:您不能使用替换函数从数组中删除值。如果您返回 undefined 或函数,则使用 null 代替。

此外,关于stringify

如果在转换过程中遇到未定义、函数或 XML 值,则它要么被忽略(当它在对象中找到时),要么被审查为 null(当它在数组中找到时)。

我无权访问您的原始对象,因此无法判断您击中的是哪两个...

如果问题出在您当前的实现中,那么实现toJSON(或只是从源对象显式构造另一个对象)而不是replacer过滤数组将是可行的方法replacer

于 2013-08-19T11:51:10.630 回答
1

为解析 json 和获取子值预定义了各种 js 库。我通常用来解析 json 的方法是使用http://developer.yahoo.com/yui/json/ YUI 库。

于 2013-08-19T11:42:11.397 回答
0

所以我最终解决了我的问题,这就是我做到的。

function cacheForm(agency) {
    // GET my object from agency vm
    var agency = ko.toJS(agency);

    var s = YUI().use("json-stringify", function (Y) {    
        var jsonStrAgency = Y.JSON.stringify(agency, ["activities", "agencyName", "agencyID", "campaignBillings", "category", "declaredBillings", "immediateParent", "numberOfEmployees", "ultimateParent", "uRL"]); // Use an array of acceptable object key names as a whitelist.
        var jsonStrOffices, jsonStrContacts;

        for (i in agency.offices) {
            jsonStrOffices = Y.JSON.stringify(agency.offices, ["address1", "address2", "address3", "address4", "address5", "agencyID", "faxNumber", "officeID", "postCode", "telephoneNumber"]);

        for (ii in agency.offices[i].contacts) {
                    jsonStrContacts = Y.JSON.stringify(agency.offices[i].contacts, ["agencyID", "emailAddress", "firstName", "jobName", "officeID", "personID", "surName", "title"]);
            }
        }

        localStorage.setItem('Agency', jsonStrAgency);
        localStorage.setItem('Offices', jsonStrOffices);
        localStorage.setItem('Contacts', jsonStrContacts);
    });
}

首先,我将我的 ko.observableArray 传递给函数 cacheForm。此参数称为代理,它是我的视图模型的一部分。

我想解析我的 observableArray 并将其转换为标准的 javascript 对象。通过使用 ko.toJS 我可以做到这一点。使用 toJS 后不会有 ko 构造函数。

然后我必须得到我的 JSON 字符串。由于我的对象有子孙,我必须分别解析这些部分。Stringify 不喜欢对象中的数组,它们将被更改为 null 并且您的子数据将丢失。

由于循环递归,我必须使用这个:

 var s = YUI().use("json-stringify", function (Y) {  

这是雅虎 API 的一部分。这是脚本参考:

<script src="http://yui.yahooapis.com/3.11.0/build/yui/yui-min.js"></script>

Y.JSON.stringify 将一个对象作为一个参数,并将一个选项参数作为一个数组。此数组的目的是包含要字符串化的对象的属性名称。从其他论坛我发现这被称为白名单。

使用我所有的 JSON 字符串,我可以将它们存储在 HTML5 本地存储中。

当页面加载时,我会检查我的本地存储是否包含数据。如果为真,我会检索我的数据并将 JSON 字符串序列化为 javascript 对象。

define(['services/datacontext'], function (dataContext) {
    var initialized = false;
    var agency;

    if (localStorage.Agency && localStorage.Offices && localStorage.Contacts) {
        var objAgency = new Object(ko.mapping.fromJSON(localStorage.getItem('Agency')));
        var objOffices = new Object(ko.mapping.fromJSON(localStorage.getItem('Offices')));
        var objContacts = new Object(ko.mapping.fromJSON(localStorage.getItem('Contacts')));

        objAgency.offices = objOffices;
        objAgency.offices._latestValue[0].contacts = objContacts;


        agency = ko.observableArray([ko.mapping.fromJS(objAgency)]);
        ko.applyBindings(agency);

        initialized = true;

    }
    else {
        agency = ko.observableArray([]);
    }

最后,我将对象重建为字符串化之前的状态,并将其映射回 observableArray,最后绑定它。

希望这可以帮助其他人使用 knockoutJS 和复杂对象的组合。

请参阅下面的完整代码:

define(['services/datacontext'], function (dataContext) {
    var initialized = false;
    var agency;

    if (localStorage.Agency && localStorage.Offices && localStorage.Contacts) {
        var objAgency = new Object(ko.mapping.fromJSON(localStorage.getItem('Agency')));
        var objOffices = new Object(ko.mapping.fromJSON(localStorage.getItem('Offices')));
        var objContacts = new Object(ko.mapping.fromJSON(localStorage.getItem('Contacts')));

        objAgency.offices = objOffices;
        objAgency.offices._latestValue[0].contacts = objContacts;


        agency = ko.observableArray([ko.mapping.fromJS(objAgency)]);
        ko.applyBindings(agency);

        initialized = true;

    }
    else {
        agency = ko.observableArray([]);
    }


    var save = function (agency, myStoredValue) {
        // Clear Cache because user submitted the form. We don't have to hold onto data anymore.
        //amplify.store("Agency", null);
        return dataContext.saveChanges(agency);
    };

    var vm = { // This is my view model, my functions are bound to it. 
        //These are wired up to my agency view
        activate: activate,
        agency: agency,
        title: 'agency',
        refresh: refresh, // call refresh function which calls get Agencies
        save: save,
        cacheForm: cacheForm
    };
    return vm;

    function activate() {

        vm.agency;

        if (initialized) {
            return;
        }

        initialized = false;

        return refresh();

    }

    function refresh() {
        return dataContext.getAgency(agency);
    }


    function cacheForm(agency) {
        // GET my object from agency vm
        var agency = ko.toJS(agency);

        var s = YUI().use("json-stringify", function (Y) {

            var jsonStrAgency = Y.JSON.stringify(agency, ["activities", "agencyName", "agencyID", "campaignBillings", "category", "declaredBillings", "immediateParent", "numberOfEmployees", "ultimateParent", "uRL"]); // Use an array of acceptable object key names as a whitelist.
            var jsonStrOffices, jsonStrContacts;

            for (i in agency.offices) {
                jsonStrOffices = Y.JSON.stringify(agency.offices, ["address1", "address2", "address3", "address4", "address5", "agencyID", "faxNumber", "officeID", "postCode", "telephoneNumber"]);

                for (ii in agency.offices[i].contacts) {
                    jsonStrContacts = Y.JSON.stringify(agency.offices[i].contacts, ["agencyID", "emailAddress", "firstName", "jobName", "officeID", "personID", "surName", "title"]);
                }
            }

            localStorage.setItem('Agency', jsonStrAgency);
            localStorage.setItem('Offices', jsonStrOffices);
            localStorage.setItem('Contacts', jsonStrContacts);
        });
    }
});
于 2013-08-23T14:22:01.213 回答