【问题标题】:Looking for the best way to populate objects with JSON.net using references寻找使用引用使用 JSON.net 填充对象的最佳方法
【发布时间】:2019-10-22 17:35:30
【问题描述】:

我在 Unity 中使用 JSON.net 来保存我的游戏数据。我创建了一个保存游戏类,其中包含我要保存的所有数据。假设我有一个角色列表和一个玩家对象,其中包含对其中一个角色的引用。使用 PreserveReferencesHandling,生成的 JSON 看起来像预期的那样:

{
  "characters":[
    {
      "$id": "1",
      "name": "char1",
      "reputation": 100
    },
...
  "player": {
    "location": "town1",
      "character": {
        "$ref": "1"
      }
  }
}

当我反序列化 Savegame 时,Character-List 和 Player 被恢复并设置了对 Character 的引用。 我现在可以将 Savegame 中的 Player 对象分配回我的 GameManager 中的 Player 对象,在整个游戏中都会使用 Player。

简而言之:GameManager.Player 被 Savegame 引用,然后被序列化。在 Savegame 中创建一个带有保存数据的新 Player 并且 Savegame.Player 被分配给 GameManager.Player。

问题是,游戏中引用 GameManager.Player 的每个部分现在仍然引用旧的 Player 对象,而 GameManager.Player 现在持有对新创建的 Player 的新引用(我希望我有道理)。

所以我可以确保没有播放器引用被缓存或者我正在尝试做什么,我可以使用来自 Savegame 的数据填充现有的播放器。 JSON.net 提供了一个名为JsonConvert.PopulateObject(string value, object target) 的方法。所以我解析了 JSON 并从中获取了 Player,但是在 Player 中填充 Character 并不是很成功,因为 JSON 的那部分只有引用而没有数据。

所以我的问题是:当从整个上下文中抓取对象时,如何使用这些引用填充对象?

以下代码的简化 sn-ps。

public class GameManager{
  public static GameManager instance; //singleton

  public List<Character> characters;
  public Player player; //<-- other classes may have a ref to this

  //...
}

public class Character{
  public string name;
  public int reputation;
  //...
}

public class Player{
  public string location;
  public Character character;
  //...
}

public class Savegame{
  public List<Character> characters;
  public Player player;

  public Savegame(){
    characters=GameManager.instance.characters;
    player=GameManager.instance.player;
  }

  public static void Save(){
    string saveJson = JsonConvert.SerializeObject(new Savegame(), Formatting.Indented,
        new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects });
        string dest = Path.Combine(Application.persistentDataPath, "gmSave.json");
        File.WriteAllText(dest, saveJson);
  }

  public static void Load(){
    string dest = Path.Combine(Application.persistentDataPath, "gmSave.json");
    string saveJson = File.ReadAllText(dest);
    Savegame savegame = JsonConvert.DeserializeObject<Savegame>(saveJson);
    JObject jo = JObject.Parse(saveJson);    
    JsonConvert.PopulateObject(jo["player"].ToString(), GameManager.instance.player);
  }
}

【问题讨论】:

  • 能否贴出实际代码,方便推理和帮助。我不了解引用是如何完成的。
  • 感谢 ipinak,我在上面添加了基本部分。

标签: c# json unity3d


【解决方案1】:

使用JSONUtility 代替这么简单的类。

您不应该填充对象。

【讨论】:

  • 如果我不填充对象而是创建新对象,所有对旧对象的引用现在都将指向一个“旧”对象,这意味着不会看到对新对象的所有更改任何引用旧对象的对象。澄清一下:如果您有使用车库 A 中的汽车的合同,并且该汽车不时得到维修,那么您总是有一辆可以工作的汽车。但是,如果在维修后制作了一份副本并放在车库 B 中,然后只有汽车 B 得到维修,那么您的汽车有一天将不再工作;)
猜你喜欢
  • 2012-03-17
  • 1970-01-01
  • 2011-08-14
  • 1970-01-01
  • 1970-01-01
  • 2012-04-04
  • 1970-01-01
  • 2021-04-12
  • 2020-10-23
相关资源
最近更新 更多