【问题标题】:JSON Circular Object Type ReviverJSON 圆形对象类型 Reviver
【发布时间】:2014-06-10 19:54:45
【问题描述】:

我正在构建一个网络应用游戏,该游戏使用用户可以操作和保存的自定义圆形对象。所有对象都连接到使用Circular-JSON 存储的圆形“玩家”对象。

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

我试过的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;
    }

加载将新播放器替换为本地存储中的播放器,但所有对象在此过程中都会丢失其类型,从而失去功能。

是否存在可以起作用的复活剂?可以写一个吗?

我想一般的问题是,有没有办法在保持类型的同时存储和检索循环对象?

【问题讨论】:

  • 使用 setPrototypeOf() - developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…。您可以在您的 reviver 中分配适当的原型。或者,您可以重新实例化,然后使用序列化值进行 extend()。
  • 几百个不同类型的对象” - 呃,什么?为什么存储类型不起作用?
  • @dandavis 我添加了我构建的复兴器的样本,但它不起作用。 IE 和 Safari 不支持 setPrototypeOf(),所以我在原型中使用了 .extend
  • @Bergi 存储类型是我错过的第一步,不知道为什么我认为我做不到。
  • @kahjav:在 MDN 页面上有一个 setPrototypeOf() 的 polyfill。

标签: javascript json object


【解决方案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);

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-02-05
    • 2013-05-25
    • 2018-04-02
    • 1970-01-01
    • 1970-01-01
    • 2012-08-05
    • 2015-01-14
    • 2022-12-03
    相关资源
    最近更新 更多