Nie jestem pewien, w jaki sposób serializacja/de-serializacja ma działać na wpisywanych obiektach w JavaScript. Na przykład, mam obiekt "MapLayer", który zawiera różne elementy i tablice. Pisałem (ale jeszcze nie testowane) następujący kod do próbują go serializacji:Serializacja Javascript typów maszyn
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;
}
Moje pytanie brzmi, w jaki sposób powstały obiekt powinien dostać rozszeregować jako obiekt MapLayer raczej niż jako obiekt ogólny. I w jaki sposób wszystkie instancje Sprite powinny zostać spersjonalizowane jako sprite? Czy powinienem używać "nowego MapLayer()" zamiast "{}"? Czy powinienem po prostu włączyć prototyp i właściwości konstruktora obiektu do serializacji? Coś jeszcze, czego mi brakuje? Czy robię to głupio? Są 2 powody nie używam rodzajowy kod serializacji/de-serializacji:
- Chcę szeregować dane płytki zoptymalizowanym formacie zamiast przechowywania reprezentacji base-10 ciąg dla każdej płytki, i mieć je wszystkie rozdzielone przecinkami.
- Nie chcę serializować zestawu klocków jako obiektu, który zostanie skonstruowany jako nowy obiekt podczas deklinalizacji, ale raczej jako odniesienie do istniejącego obiektu. Czy jest to możliwe przy użyciu kodu, który zaproponowałem powyżej?
Edytuj: Przepraszam za brak właściwej terminologii; JavaScript jest jednym z moich mniej zaawansowanych języków. Co mam na myśli mówiąc "Typed Object" to obiekt z konstruktorem. W tym przykładzie, mój konstruktor jest:
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;
}
Edit 2: Biorąc kod z odpowiedzią Sime Vidas', dodałem powiązany obiekt o nazwie "Device":
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);
Teraz pytanie jak najlepiej włączyć takie zależne obiekty, ponieważ ponownie "typ" (prototyp?) obiektu zostanie utracony przez JSON. Zamiast uruchamiać konstruktora, dlaczego po prostu nie zmienimy funkcji przekształcania do postaci szeregowej i dekretyzacji, aby zapewnić, że obiekt będzie musiał zostać skonstruowany tylko raz, zamiast tworzyć i kopiować?
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);
};
Edit 3: Innym problemem jest to, że mam JSON nie wydają się działać w IE9. Używam tego pliku testowego:
<html>
<head>
<title>Script test</title>
<script language="javascript">
console.log(JSON);
</script>
</head>
</html>
a wyjścia konsoli:
SCRIPT5009: 'JSON' is undefined
test.html, line 5 character 1
Edycja 4: Aby rozwiązać ten problem JSON muszę zawierać poprawny tag DOCTYPE na początku.
Co to jest wpisany obiekt? –
Obiekt z konstruktorem innym niż "Obiekt". Nie wiem, jak to nazwać. – BlueMonkMN
Ach, masz na myśli obiekty będące instancjami własnych konstruktorów ('MapLayer',' Sprite', itp.) ... –