admin管理员组

文章数量:1313170

How do I serialize these classes to JSON?

As you can see from the example below JSON.stringify() does not serialize the list of Cache_Backend_LocalStorage_Tag inside the Cache_Backend_LocalStorage_TagThree object.

What am I missing?

interface Cache_Backend_LocalStorage_Tag_Interface {
    _tag : string;
    _keys : string[];
}

class Cache_Backend_LocalStorage_Tag implements Cache_Backend_LocalStorage_Tag_Interface {

    public _tag : string;
    public _keys : string[];

    constructor(tag : string) {
        this._tag = tag;

        this._keys = [];
    }

    public add(key : string) : void {
        this._keys.push(key);   
    }

    public remove(key : string): boolean {
        // Get the index of the key
        var index = this._keys.indexOf(key, 0);

        // Check if we found the keys index
        if (index != undefined) {
           this._keys.splice(index, 1);

           return true;
        }

        return false;
    }

    public get tag(): string {
        return this._tag;
    }

    public get keys(): string[] {
        return this._keys;
    }
}

interface Cache_Backend_LocalStorage_TagThree_Interface {
    _tags : Cache_Backend_LocalStorage_Tag[];
}

class Cache_Backend_LocalStorage_TagThree implements Cache_Backend_LocalStorage_TagThree_Interface {

    public _tags : Cache_Backend_LocalStorage_Tag[];

    constructor(tags : Cache_Backend_LocalStorage_Tag[] = []) {
        this._tags = tags;
    }

    public add(tag : Cache_Backend_LocalStorage_Tag) : void {
        this.tags[tag.tag] = tag;
    }

    public get tags(): Cache_Backend_LocalStorage_Tag[] {
        return this._tags;
    }

    public get(tagKey : string): Cache_Backend_LocalStorage_Tag {
        return this.tags[tagKey];
    }

    public addKeyToTag(tagKey, key) {
        this.tags[tagKey].add(key);
    }

    public removeKeyFromTag(tagKey, key) {
        // Get the tag
        var tag = this._tags[tagKey];

        // Check if we found the tag index
        if (tag != undefined) {
            return tag.remove(key);
        }

        return false;
    }

    public clear(tagKey : string): void {
        delete this._tags[tagKey];
    }

    public static fromObject(object): Cache_Backend_LocalStorage_TagThree {
        return new Cache_Backend_LocalStorage_TagThree(object._tags);
    }
}

Issue:

var tagThree = new Cache_Backend_LocalStorage_TagThree();
tagThree.add(new Cache_Backend_LocalStorage_Tag("stores"));
tagThree.addKeyToTag("stores", "store5");
tagThree.removeKeyFromTag("stores", "store5");

//  {"_tags":[]}
console.log(JSON.stringify(tagThree));

// { _tags: [ stores: { _tag: 'stores', _keys: [Object] } ] }
console.log(tagThree);

How do I serialize these classes to JSON?

As you can see from the example below JSON.stringify() does not serialize the list of Cache_Backend_LocalStorage_Tag inside the Cache_Backend_LocalStorage_TagThree object.

What am I missing?

interface Cache_Backend_LocalStorage_Tag_Interface {
    _tag : string;
    _keys : string[];
}

class Cache_Backend_LocalStorage_Tag implements Cache_Backend_LocalStorage_Tag_Interface {

    public _tag : string;
    public _keys : string[];

    constructor(tag : string) {
        this._tag = tag;

        this._keys = [];
    }

    public add(key : string) : void {
        this._keys.push(key);   
    }

    public remove(key : string): boolean {
        // Get the index of the key
        var index = this._keys.indexOf(key, 0);

        // Check if we found the keys index
        if (index != undefined) {
           this._keys.splice(index, 1);

           return true;
        }

        return false;
    }

    public get tag(): string {
        return this._tag;
    }

    public get keys(): string[] {
        return this._keys;
    }
}

interface Cache_Backend_LocalStorage_TagThree_Interface {
    _tags : Cache_Backend_LocalStorage_Tag[];
}

class Cache_Backend_LocalStorage_TagThree implements Cache_Backend_LocalStorage_TagThree_Interface {

    public _tags : Cache_Backend_LocalStorage_Tag[];

    constructor(tags : Cache_Backend_LocalStorage_Tag[] = []) {
        this._tags = tags;
    }

    public add(tag : Cache_Backend_LocalStorage_Tag) : void {
        this.tags[tag.tag] = tag;
    }

    public get tags(): Cache_Backend_LocalStorage_Tag[] {
        return this._tags;
    }

    public get(tagKey : string): Cache_Backend_LocalStorage_Tag {
        return this.tags[tagKey];
    }

    public addKeyToTag(tagKey, key) {
        this.tags[tagKey].add(key);
    }

    public removeKeyFromTag(tagKey, key) {
        // Get the tag
        var tag = this._tags[tagKey];

        // Check if we found the tag index
        if (tag != undefined) {
            return tag.remove(key);
        }

        return false;
    }

    public clear(tagKey : string): void {
        delete this._tags[tagKey];
    }

    public static fromObject(object): Cache_Backend_LocalStorage_TagThree {
        return new Cache_Backend_LocalStorage_TagThree(object._tags);
    }
}

Issue:

var tagThree = new Cache_Backend_LocalStorage_TagThree();
tagThree.add(new Cache_Backend_LocalStorage_Tag("stores"));
tagThree.addKeyToTag("stores", "store5");
tagThree.removeKeyFromTag("stores", "store5");

//  {"_tags":[]}
console.log(JSON.stringify(tagThree));

// { _tags: [ stores: { _tag: 'stores', _keys: [Object] } ] }
console.log(tagThree);
Share Improve this question edited Mar 23, 2015 at 16:27 David Sherret 107k28 gold badges196 silver badges185 bronze badges asked Mar 23, 2015 at 15:34 user634545user634545 9,4295 gold badges31 silver badges41 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 5

Reason

It's because you're assigning properties to an array and array properties won't be included in JSON serialization. For example:

var a = [];
a["test"] = "some value";
JSON.stringify(a); // returns: []

You need to use a plain object:

var o = {};
o["test"] = "some value";
JSON.stringify(o); // returns: {"test":"some value"} 

Solution

Change your Cache_Backend_LocalStorage_TagThree_Interface interface to use a dictionary like object:

interface Cache_Backend_LocalStorage_TagThree_Interface {
    _tags : { [tag: string] : Cache_Backend_LocalStorage_Tag; };
}

Then update all areas of the code that will now have a pile error to use the same type. For example, change:

constructor(tags : Cache_Backend_LocalStorage_Tag[] = []) {

To:

constructor(tags : { [tag: string] : Cache_Backend_LocalStorage_Tag; } = {}) {

Just for fun - Changing default serialization behaviour (Not remended)

If you really want to make this work with an array with your current setup (I'm not sure why), you can override how serialization is done. To do this, add a toJSON method to the _tags array in Cache_Backend_LocalStorage_TagThree. This allows you to control how the object is serialized when JSON.stringify is called on it. For example:

this._tags.toJSON = function() {
    var values = [];

    for (var v in this) {
        if (this[v] instanceof Cache_Backend_LocalStorage_Tag) {
            values.push(this[v]);
        }
    }

    return JSON.stringify(values);
};

本文标签: javascriptTypeScriptserialize class objectsStack Overflow