0

親と子のデータを含む JSON 文字列を返す JSON.stringify で文字列化する JavaScript オブジェクトがあります。

この文字列を解析してオブジェクトに戻そうとすると、子オブジェクトが null になります。

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

注: replacer 関数を使用して配列から値を削除することはできません。undefined または関数を返す場合は、代わりに null が使用されます。

さらに、以下についてstringify

未定義、関数、または XML 値が変換中に検出された場合、それらは省略されるか (オブジェクトで見つかった場合)、null に打ち切られます (配列で見つかった場合)。

私はあなたの元のオブジェクトにアクセスできないため、あなたがどちらを攻撃しているのかわかりません...

問題が現在の実装内にある場合は、配列をフィルター処理する代わりに実装toJSON(または単にソース オブジェクトから別のオブジェクトを明示的に構築)する方法があります。replacerreplacer

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

これは Yahoo API の一部です。これはスクリプト リファレンスです。

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

Y.JSON.stringify は、オブジェクトを 1 つのパラメーターとして受け取り、配列であるオプション パラメーターを受け取ります。この配列の目的は、文字列化するオブジェクトのプロパティ名を含めることです。他のフォーラムから、これがホワイトリストとして知られていることがわかりました。

すべての 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);
        });
    }
});
于 2013-08-23T14:22:01.213 に答える