寻找使用引用填充 JSON.net 对象的最佳方法



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

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

当我反序列化保存游戏时,角色列表和玩家被恢复,并且对角色的引用被设置。 现在,我可以将 Savegame 中的玩家对象分配回我的游戏管理器中的玩家对象,在整个游戏中使用播放器。

简而言之:GameManager.Player被Savegame引用,然后被序列化。加载带有保存数据的新播放器后,将在Savegame中创建,Savegame.Player被分配给GameManager.Player。

问题是,游戏中引用了 GameManager.Player 的每个部分现在仍然引用旧的 Player-对象,而 GameManager.Player 现在保留了对新创建的 Player 的新引用(我希望我有意义)。

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

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

下面的简化代码片段。

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

对于这么简单的类,请使用JSONUtility

不应填充对象。

最新更新