2011-12-28 20 views
8

Tôi không rõ cách serialization/de-serialization được cho là hoạt động trên các đối tượng đã nhập trong JavaScript. Ví dụ, tôi có một đối tượng "MapLayer" có chứa các thành viên và mảng khác nhau. Tôi đã viết (nhưng chưa được kiểm tra) đoạn mã sau để cố gắng serialize nó:Làm theo tuần tự hóa Javascript của các đối tượng đã nhập

MapLayer.prototype.serialize = function() { 
    var result = "{tileset:tilesets." + tilesets.getTilesetName(this.tileset) + ",columns:" + this.columns + ",rows:" + this.rows + 
    ",offsetX:" + this.offsetX + ",offsetY:" + this.offsetY + ",currentX:" + this.currentX + ",currentY:" + this.currentY + 
    ",scrollRateX:" + this.scrollRateX + ",scrollRateY:" + this.scrollRateY + ",virtualColumns:" + this.virtualColumns + ",virtualRows:" + this.virtualRows + 
    ",tiles:\"" + this.encodeTileData2() + "\""; 
    for(key in this) 
    { 
     if(this[key] instanceof Sprite) 
     result += "," + key + ":" + this[key].serialize(); 
    } 
    return result; 
} 

Câu hỏi của tôi là, làm thế nào là đối tượng kết quả phải được deserialized như một đối tượng MapLayer chứ không phải là một đối tượng chung chung. Và làm thế nào là tất cả các trường hợp Sprite được cho là được deserialized như sprites. Tôi có nên sử dụng "MapLayer mới()" thay vì "{}" không? Hoặc tôi chỉ đơn giản là nghĩa vụ phải bao gồm các nguyên mẫu và tính chất constructor của đối tượng trong serialization? Tôi còn thiếu cái gì nữa không? Tôi đang làm điều này một cách ngu ngốc? Có 2 lý do tôi không sử dụng mã tuần tự hóa/de-serialization chung:

  1. Tôi muốn tuần tự hóa dữ liệu ô theo định dạng được tối ưu hóa thay vì lưu trữ biểu diễn chuỗi cơ sở cho mỗi ô và có chúng tất cả được phân tách bằng dấu phẩy.
  2. Tôi không muốn sắp xếp hàng loạt tileet làm đối tượng được tạo thành đối tượng mới trong quá trình hủy tuần tự hóa, mà là tham chiếu đến đối tượng hiện có. Có thể sử dụng mã như tôi đã đề xuất ở trên không?

Chỉnh sửa: Xin lỗi vì thiếu thuật ngữ thích hợp; JavaScript là một trong những ngôn ngữ ít chuyên môn của tôi. Những gì tôi có nghĩa là khi tôi nói "Typed Object" là một đối tượng với một constructor. Trong ví dụ này, constructor của tôi là:

function MapLayer(map, tileset, columns, rows, virtualColumns, virtualRows, offsetX, offsetY, scrollRateX, scrollRateY, priority, tileData) { 
    this.map = map; 
    this.tileset = tileset; 
    this.columns = columns; 
    this.rows = rows; 
    this.offsetX = offsetX; 
    this.offsetY = offsetY; 
    this.currentX = offsetX; 
    this.currentY = offsetY; 
    this.scrollRateX = scrollRateX; 
    this.scrollRateY = scrollRateY; 
    if(tileData.length < columns * rows * 2) 
     this.tiles = DecodeData1(tileData); 
    else 
     this.tiles = DecodeData2(tileData); 
    this.virtualColumns = virtualColumns ? virtualColumns : columns; 
    this.virtualRows = virtualRows ? virtualRows : rows; 
} 

Chỉnh sửa 2: Lấy mã từ Šime Vidas' câu trả lời, tôi đã thêm một đối tượng liên quan được gọi là "thiết bị":

function Device(description, memory) { 
    this.description = description; 
    this.memory = memory; 
} 

function Person(name, sex, age, devices) { 
    this.name = name; 
    this.sex = sex; 
    this.age = age; 
    this.devices = devices; 
} 

Person.deserialize = function (input) { 
    var obj = JSON.parse(input); 
    return new Person(obj.name, obj.sex, obj.age, obj.devices); 
}; 

var device = new Device('Blackberry', 64); 
var device2 = new Device('Playstation 3', 600000); 
var person = new Person('John', 'male', 25, [device, device2]); 

var string = JSON.stringify(person); 
console.log(string); 

var person2 = Person.deserialize(string); 
console.log(person2); 
console.log(person2 instanceof Person); 

Bây giờ câu hỏi là cách tốt nhất để kết hợp các đối tượng phụ thuộc như vậy, bởi vì một lần nữa, "kiểu" (nguyên mẫu?) của đối tượng bị mất bởi JSON. Thay vì chạy hàm khởi tạo, tại sao chúng ta không đơn giản thay đổi tuần tự hóa và các hàm de-serialize để đảm bảo rằng đối tượng chỉ cần được xây dựng một lần như thế này thay vì tạo và sao chép?

Person.prototype.serialize = function() { 
    var obj = this; 
    return '({ ' + Object.getOwnPropertyNames(this).map(function (key) { 
     var value = obj[key]; 
     if (typeof value === 'string') { value = '"' + value + '"'; } 
     return key + ': ' + value; 
    }).join(', ') + ',"__proto__":Person.prototype})'; 
}; 

Person.deserialize = function (input) { 
    return eval(input); 
}; 

Sửa 3: Một vấn đề tôi đã là JSON dường như không làm việc trong IE9. Tôi đang sử dụng tập tin này kiểm tra:

<html> 
<head> 
<title>Script test</title> 
<script language="javascript"> 
console.log(JSON); 
</script> 
</head> 
</html> 

Và giao diện điều khiển đầu ra:

SCRIPT5009: 'JSON' is undefined 
test.html, line 5 character 1 

Sửa 4: Để khắc phục sự cố JSON tôi phải bao gồm thẻ DOCTYPE đúng ngay từ đầu.

+1

Đối tượng được nhập là gì? –

+0

Một đối tượng với một hàm tạo khác với "Đối tượng". Tôi không biết phải gọi nó là gì. – BlueMonkMN

+0

Ah, bạn có nghĩa là các đối tượng là trường hợp của các nhà xây dựng của riêng bạn ('MapLayer',' Sprite', v.v.) ... –

Trả lời

8

Đối với một sự khởi đầu, đây là một ví dụ đơn giản tùy chỉnh serialization/deserialization:

function Person(name, sex, age) { 
    this.name = name; 
    this.sex = sex; 
    this.age = age; 
} 

Person.prototype.serialize = function() { 
    var obj = this; 
    return '{ ' + Object.getOwnPropertyNames(this).map(function (key) { 
     var value = obj[key]; 
     if (typeof value === 'string') { value = '"' + value + '"'; } 
     return '"' + key + '": ' + value; 
    }).join(', ') + ' }'; 
}; 

Person.deserialize = function (input) { 
    var obj = JSON.parse(input); 
    return new Person(obj.name, obj.sex, obj.age); 
}; 

Cách sử dụng:

Đầu tiên, chúng ta tạo ra một đối tượng dụ mới:

var person = new Person('John', 'male', 25); 

Bây giờ, chúng tôi tuần tự hóa đối tượng đó thành một chuỗi bằng cách sử dụng phương thức Person.prototype.serialize:

var string = person.serialize(); 

Điều này sẽ cho sử dụng chuỗi này:

{ "name": "John", "sex": "male", "age": 25 } 

Cuối cùng, chúng tôi deserialize rằng chuỗi bằng cách sử dụng Person.deserialize phương pháp tĩnh:

var person2 = Person.deserialize(string); 

Bây giờ, person2 là một thể hiện của Person và chứa thuộc tính tương tự các giá trị như phiên bản gốc person.

Live Demo:http://jsfiddle.net/VMqQN/


Bây giờ, trong khi Person.deserialize phương pháp tĩnh là cần thiết trong trường hợp bất kỳ (nó sử dụng JSON.parse nội bộ, và gọi các nhà xây dựng Person để khởi tạo một đối tượng mới), phương pháp Person.prototype.serialize mặt khác, chỉ cần thiết nếu phương pháp tĩnh được xây dựng trong JSON.stringify không đủ.

Trong ví dụ của tôi ở trên var string = JSON.stringify(person) cũng sẽ hoàn thành công việc, do đó, không cần cơ chế tuần tự tùy chỉnh. Xem tại đây: http://jsfiddle.net/VMqQN/1/ Tuy nhiên, trường hợp của bạn phức tạp hơn, vì vậy bạn sẽ cần xác định chức năng tuần tự hóa tùy chỉnh.

+1

+1. Ví dụ tuyệt vời. –

+0

Tôi đã cập nhật câu hỏi. Tại sao chúng ta không đặt '__proto__' thay vì gọi hàm tạo? – BlueMonkMN

+0

Một vấn đề khác là, nếu tôi cố gắng sử dụng JSON trong IE, tôi gặp lỗi "JSON không xác định". – BlueMonkMN

1

Nếu bạn nhìn vào dự án ST-JS (http://st-js.org), nó cho phép tạo biểu đồ đối tượng của bạn ở Java ở phía máy chủ, tuần tự hóa nó trong JSON và deserialize nó ở phía máy khách (Javascript) theo cách được nhập , tức là các đối tượng sẽ được khởi tạo bằng cách sử dụng hàm tạo của chúng và bạn có thể gọi các phương thức trên các đối tượng đã tạo.

Để sử dụng ST-JS, bạn nên viết mã máy khách là Java, được chuyển đổi gần như một trong một trong Javascript.

Chương AJAX/JSON trên trang chủ của trang web giải thích cho bạn cách phân tích chuỗi JSON trong khi vẫn giữ thông tin loại.

+0

Tôi nghĩ rằng OP đã hỏi về các kỹ thuật để sử dụng cho codebase hiện tại của họ, chứ không phải là một khung công tác khác để di chuyển đến. –

+0

Có bạn bằng cách nào đó đúng. Vấn đề tôi đã chỉ ra là để có thể deserialize một cách chung chung một đồ thị của các đối tượng "gõ" (như trong Edit 2) bạn cần bằng cách nào đó lưu trữ một số siêu dữ liệu về "đối tượng đánh máy" của bạn, tức là để nói với deserializer của bạn mà ví dụ "thiết bị" tài sản của "Người" là một mảng của "Thiết bị". –

+0

Nếu bạn xem [nguồn] của chúng tôi (https://github.com/st-js/st-js/blob/master/generator/src/main/resources/stjs.js) hàm parseJSON (đó là có thể dễ dàng trích xuất) sử dụng trường "tĩnh" được gọi là "typeDescription", đó là một bản đồ đơn giản - khung của chúng tôi tạo ra, nhưng cũng có thể được tạo theo cách thủ công. –

Các vấn đề liên quan