1

我正在寻找一种 Javascript 对象的序列化方法,该对象包含其他几个不同类的对象,带有函数参数。

这是一个简单的测试用例:

// Paper class:

function Paper(name) {
    this.name = name;
} 
Paper.prototype = {
    string: function() { return "Paper:"+this.name; }
};


// Book class:

function Book(name) {
    this.name = name;
} 
Book.prototype = {
    string: function() { return "Book:"+this.name; }
};


// Library class:

function Library(name) {
    this.items = [];
}
Library.prototype = {
    add: function(item) { this.items.push(item); },
    string: function () {
        var titles = this.items.map(function(item) { return item.string(); });
        return titles.join(",");
    },
};


///// Define a library:

var lib = new Library();
lib.add(new Paper("MyPaper"));
lib.add(new Book("MyBook"));
assert(lib.string() == "Paper:MyPaper,Book:MyBook");

///// Serialize, de-serialize and compare:

// var libString = serialize(lib);
// var newLib = deserialize(libString);
// assert(newLib.string() == "Paper:MyPaper,Book:MyBook");

注意:反序列化的主要用途(至少在我的情况下)是将复杂对象移动到远程计算机。例如,我想在我的计算机上构建一个大库,然后对其进行序列化,放入一个文件,将文件发送到另一台计算机,在那里对其进行反序列化,并拥有完全相同的库。

4

2 回答 2

1

您需要扩展 JSON 语义。如果我是你,我会这样做:

var protos = {}, //hash of prototypes
base = {  //base prototype
     toJSON: function () {
         var props = {}; //properties to be serialized

         for (var prop in this) { //this can be custimized, like taking `attrs` hash or something
             if (this.hasOwnProperty(prop)) props[prop] = this[prop];
         }

        props.$proto = this.$proto; //need to copy this manually since it's not an `own propery`

        return props;
    }
};

function Paper(name) {
    this.name = name;
} 

protos.paper = Paper.prototype = Object.create(base);

Paper.prototype.$proto = 'paper';

Paper.prototype.toString = function() { 
    return 'Paper: ' + this.name; 
}

function Book(name) {
    this.name = name;
} 

protos.book = Book.prototype = Object.create(base);

Book.prototype.$proto = 'book';

Book.prototype.toString = function() { 
    return 'Book: ' + this.name; 
}


function Library(name) {
    this.items = [];
}

Library.prototype = {
    add: function(item) { this.items.push(item); },
    toString: function () {
        var titles = this.items.map(function(item) { 
            return item.toString(); 
        });

        return titles.join(',');
    },
    toJSON: function () {
        return this.items.map(function(item) { return item.toJSON()});
    }
};

Library.fromJSON = function (json) {
    return json.map(function(item) {
        var object = Object.create(protos[item.$proto]);

        for (var prop in item) object[prop] = item[prop];

        return object;
    });
};

//test

var lib = new Library();
lib.add(new Paper('MyPaper'));
lib.add(new Book('MyBook'));

console.log(lib.toString());

var json = JSON.stringify(lib.toJSON());

console.log(Library.fromJSON(JSON.parse(json)).toString());

这是一个小提琴:http: //jsfiddle.net/cSTT5/

于 2013-10-17T13:29:51.753 回答
0

我想在我的计算机上构建一个大库,然后对其进行序列化,放入一个文件,将文件发送到另一台计算机,在那里对其进行反序列化,并拥有完全相同的库。

我制作了一个名为esserializer的 npm 模块来解决这个问题:在序列化过程中以纯 JSON 格式递归地保存 JavaScript 类实例值及其类名信息。然后,在反序列化阶段,esserializer 可以使用相同的类定义递归反序列化对象实例,并保留所有类型/函数信息。

对于您的方案,代码非常简单。如果将序列化的字符串带到另一台计算机上,只要该计算机上存在相同的类定义,它就可以工作:

const ESSerializer = require('esserializer');

// Paper class:
function Paper(name) {
  this.name = name;
}
Paper.prototype = {
  string: function() { return "Paper:"+this.name; }
};
Paper.prototype.constructor = Paper; // We need to redefine the constructor of Paper's prototype.

// Book class:
function Book(name) {
  this.name = name;
}
Book.prototype = {
  string: function() { return "Book:"+this.name; }
};
Book.prototype.constructor = Book;

// Library class:
function Library(name) {
  this.items = [];
}
Library.prototype = {
  add: function(item) { this.items.push(item); },
  string: function () {
    var titles = this.items.map(function(item) { return item.string(); });
    return titles.join(",");
  },
};
Library.prototype.constructor = Library;

///// Define a library:
var lib = new Library();
lib.add(new Paper("MyPaper"));
lib.add(new Book("MyBook"));
// assert(lib.string() == "Paper:MyPaper,Book:MyBook");

var serializedString = ESSerializer.serialize(lib);

// Later, on another machine, deserializedObj is a perfect copy of "lib":
var deserializedObj = ESSerializer.deserialize(serializedString, [Library, Book, Paper]);
console.log(deserializedObj.string()); // Paper:MyPaper,Book:MyBook
于 2021-03-18T04:12:54.777 回答