Сериализация типизированных объектов в Javascript

Мне неясно, как сериализация / десериализация должна работать с типизированными объектами в JavaScript. Например, у меня есть объект «MapLayer», содержащий различные члены и массивы. Я написал (но еще не протестирован) следующий код, чтобы попытаться сериализовать его:

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;
}

Мой вопрос в том, как должен десериализоваться результирующий объект как объект MapLayer, а не как общий объект. И как предполагаются все экземпляры Sprite для десериализации в виде спрайтов. Должен ли я использовать «new MapLayer ()» вместо «{}»? Или я просто должен включить свойства прототипа и конструктора объекта в сериализацию? Что-нибудь еще мне не хватает? Я делаю это глупо? Есть 2 причины, по которым я не использую общий код сериализации / десериализации:

  1. Я хочу сериализовать данные плитки в оптимизированном формате, а не хранить строковое представление base-10 для каждой плитки , и все они должны быть разделены запятыми.
  2. Я не хочу сериализовать tileset как объект, который создается как новый объект во время десериализации, а скорее как ссылка на существующий объект. Возможно ли это с использованием кода, подобного тому, что я предложил выше?

Изменить: Извините за отсутствие правильной терминологии; JavaScript - один из моих менее опытных языков. Что я имел в виду, когда сказал «Типизированный объект» - это объект с конструктором.В этом примере мой конструктор:

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;
}

Редактировать 2: Взяв код из ответа Шиме Видаса, я добавил связанный объект под названием «Устройство»:

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 );

Теперь вопрос в том, как лучше всего включить такие зависимые объекты, потому что еще раз, "тип" (прототип?) объекта теряется JSON. Вместо того, чтобы запускать конструктор, почему бы нам просто не изменить функции сериализации и десериализации, чтобы гарантировать, что объект нужно создать только один раз, как это, вместо того, чтобы создавать и копировать?

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 );
};

Редактировать 3: Еще одна проблема, с которой я столкнулся, заключается в том, что JSON, похоже, не работает в IE9. Я использую этот тестовый файл:

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

И консоль выводит:

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

Редактировать 4: Чтобы исправить проблему с JSON, я должен включить в начало правильный тег DOCTYPE.

8
задан BlueMonkMN 31 December 2011 в 15:21
поделиться