JSON循环对象类型恢复器

JSON Circular Object Type Reviver

本文关键字:恢复 类型 对象 循环 JSON      更新时间:2023-09-26

我正在构建一个使用用户可以操作和保存的自定义圆形对象的web应用游戏。所有的对象都连接到一个使用circular - json存储的圆形'player'对象。

应用程序要求保留对象类型,但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;
    }

加载用本地存储上的播放器替换新播放器,但在此过程中所有对象都失去了它们的类型,从而失去了功能。

是否存在有效的恢复器?有可能写一篇吗?

我猜一般的问题是,是否有一种方法来存储和检索循环对象,同时保持类型?

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

传递键和构造函数名称(您甚至可以通过遵循约定进一步简化此操作),在键处解析对象,然后将其注入新的构造函数。此后,只需将构造函数名称的小写版本赋值即可。您还可以遍历这些值并找到'~'。