JSON.parse返回具有空值的子对象,未解析子值

时间:2013-08-19 11:27:34

标签: javascript json

我有一个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字符串的对象中可用。我可能会在帖子中删除此代码,因为我的原始代码有很多注释。

My agency object before stringify - it has child data

3 个答案:

答案 0 :(得分:3)

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

这不是解析错误,而是stringify中的错误。您的粘贴已有data.offices = [null]

关于replacer

MDN州:

  

注意:您无法使用replacer函数从数组中删除值。如果返回undefined或函数,则使用null。

此外关于stringify

  

如果在转换过程中遇到未定义,函数或XML值,则将其省略(在对象中找到它)或删除为null(在数组中找到它时)。

我无法访问您的原始对象,因此无法判断您正在击中哪一个......

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

答案 1 :(得分:1)

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

答案 2 :(得分: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。此参数称为代理,它是我的viewmodel的一部分。

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

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

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

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

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

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

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

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

当页面加载时,然后检查我的本地存储是否包含数据。如果为true,我将检索我的数据并从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([]);
    }

最后,我将对象重建为stringify之前的对象,然后将其映射回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);
        });
    }
});