2014-06-10 5 views
4

Я создаю игру в веб-приложении, в которой используются пользовательские круглые объекты, которые пользователь может манипулировать и сохранять. Все объекты подключены к круговому «игровому» объекту, который хранится с использованием Circular-JSON.JSON Circular Object Type Reviver

Приложение требует сохранения типов объектов, но JSON этого не делает. Я не могу объявить тип для каждого отдельного объекта, потому что у игрока может быть пара сотен объектов разных типов. Я видел некоторые реверсивные, которые относятся к типу, но не к родовому, или к одному, который работал бы с круговыми объектами.

Например:

function Room(name, description){ 
      this.type = "room"; 
    this.name = name; 
    this.description = description; 
    this.roomItems = [/*array of items randomly set*/]; 
    this.exits = [/*array of rooms set */]; 
} 

function Item(name, description, weight){ 
      this.type = "item"; 
    this.name = name; 
    this.description = description; 
    this.weight = weight; 
    this.components = [/*array of items*/]; 
    this.contents = []; 
    this.setContents = function(item){ 
     this.contents.push(item); 
     this.weight += item.weight; 
    } 
} 

function Player(startroom){ 
      this.type = "player" 
    this.weightLimit = 20; 
    this.totalWeight = 0; 
    this.currentRoom = startroom; //this is a room 
    this.playerItems = [/* An array of Items */]; 
    this.moveCount = 0; 
} 

Приложение сохраняет и загружает через:

function saveGame(){  
    var d = new Date() 
    player.lastsave = d.toISOString(); 
    localStorage.setItem('player', CircularJSON.stringify(player)); 
} 

function loadGame(){ 
    declareStart(); //loads the same as a start 
    player = CircularJSON.parse(localStorage.getItem('player', reviver)); 
} 

Возрождения Я попытался это следующим образом:

function reviver(k, v){ 
     switch (v.type) { 
      case "room": 
       $.extend(v, Room.prototype); 
       break; 
      case "item": 
       $.extend(v, Item.prototype); 
       break; 
      case "player": 
       $.extend(v, Player.prototype); 
       break; 
     } 
     return v; 
    } 

Нагрузка заменяет новый игрок с игрок на локальном хранилище, но все объекты теряют свой тип в процессе, который затем теряет функциональность.

Существует ли reviver, который будет работать? Можно ли написать одно?

Я думаю, что общий вопрос будет, есть ли способ хранения и извлечения круговых объектов при сохранении типа?

+1

using setPrototypeOf() - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf. вы можете назначить правильные прототипы в своем реверсе. альтернативно, вы можете повторно создать экземпляр и затем расширить() с помощью сериализованных значений. – dandavis

+0

«Несколько сотен объектов разных типов *» - э-э, что? И почему сохранение типа не работает? – Bergi

+0

@ dandavis Я добавил образец создателя, который я построил, и он не сработал. setPrototypeOf() не поддерживается IE и Safari, поэтому я использовал .extend с прототипом – kahjav

ответ

1

@kahjav Вы, безусловно, можете оживить типы с помощью Object.create, используя самоанализ на имени методы конструктора & используя условность именования циклической ссылки на ключе, что это так же, как имя нижнего регистра конструктора. См. Мой раздел: https://gist.github.com/jameswomack/6e6462f9c6ae5d9b9072

Из-за того, что был создан модуль CircularJSON, вы не можете сохранить тип как для родительского объекта, так и для круговой ссылки с помощью CircularJSON.

Там по существу два этапа

function get(key, Proto) { 
    var result = JSON.parse(this.store[key]); 
    return key === Proto.name.toLowerCase() ? reviveFromJSONResult(result, Proto) : result; 
} 

function reviveFromJSONResult(result, Proto) { 
    var value = Object.create(Proto); 
    for (var key in result) { 
    value[key] = result[key]; 
    } 
    value[Proto.name.toLowerCase()] && (value[Proto.name.toLowerCase()] = value); 
    return value; 
} 

var person = get('person', Person); 

Вы передаете ключ и имя конструктора (можно даже упростить это далее следуя конвенции), разобрать объект на ключ, а затем вводят его в новый конструктор. После этого вы просто назначаете нижнюю версию имени конструктора. Вы также можете перебирать значения и находить «~».