【问题标题】:JSON.parse returns children objects with null value, children values not being parsedJSON.parse 返回具有空值的子对象,子值不被解析
【发布时间】:2013-08-23 22:22:01
【问题描述】:

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

【问题讨论】:

  • 查看实际的 JSON 会对我们有所帮助,如果可能的话,您可以发布指向它的链接吗?
  • 使用 fpaste.org 或使用 paste bin 来粘贴你的 json
  • 是的,给我们实际数据。无论如何,我的赌注是“注意:您不能使用替换函数从数组中删除值。如果您返回 undefined 或函数,则使用 null 代替。” (MDN)
  • fpaste.org/33076/37691240 密码是测试
  • 在您在链接中提供的 json 中,offices 已经是一个数组,其中一个元素为空。我们可以看到实际对象的原始 JSON。

标签: javascript json


【解决方案1】:

您的问题最初显示了一个屏幕截图,其中突出显示了data.offices = [null]

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

MDN 声明关于replacer

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

还有关于stringify:

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

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

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

【讨论】:

  • 我不确定我会提供什么来对其进行字符串化以过滤数组。你有例子吗?
  • 文档指出:您不能向stringify 提供任何东西来过滤数组。您可以构造一个已经过滤的对象并将其提供给stringify,或者通过在您的对象上实现toJSON 来隐式地提供,或者像JSON.stringify(doFilterMyObject(obj)) 一样显式地提供。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

    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) {  
    

    这是 Yahoo 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([]);
        }
    

    最后,我将我的对象重建为 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);
            });
        }
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-11
      • 2018-12-22
      • 1970-01-01
      • 2018-12-30
      相关资源
      最近更新 更多