C#中Dictionary<string, object>转类型遇InvalidCastException问题求助
解决Dictionary<string, object>反序列化后int强转System.InvalidCastException问题
问题原因
Newtonsoft.Json在反序列化无类型的Dictionary<string, object>时,会将JSON中的整数默认解析为long类型(而非int)。当你用(int)直接强制转换装箱后的long对象时,就会抛出System.InvalidCastException——因为装箱值的实际类型与目标类型不匹配。此外,ObservableCollection<LevelCardGroup>的强转也可能失败,因为反序列化返回的通常是List<LevelCardGroup>而非ObservableCollection。
解决方案
方案1:直接反序列化为GameStats(最优解)
跳过Dictionary中转,直接将JSON字符串反序列化为GameStats对象,让Newtonsoft.Json自动处理类型映射,彻底避免手动转换的问题:
public async Task ReadGameFileInAsync(string gameVersion) { string filePath = gameVersion == "bronze" ? BronzeGameSaveFilePath : SilverGameSaveFilePath; string jsonContent = await ReadFileInAsync(filePath); // 直接反序列化为GameStats实例 var loadedStats = JsonConvert.DeserializeObject<GameStats>(jsonContent); // 同步属性到_GameStats _GameStats.CurrentGame = loadedStats.CurrentGame; _GameStats.CurrentWord = loadedStats.CurrentWord; _GameStats.Score = loadedStats.Score; _GameStats.BestScore = loadedStats.BestScore; _GameStats.Difficulty = loadedStats.Difficulty; _GameStats.IsNewGame = loadedStats.IsNewGame; _GameStats.IsContinue = loadedStats.IsContinue; _GameStats.IsUnlocked = loadedStats.IsUnlocked; _GameStats.GameVersion = loadedStats.GameVersion; // 转换List为ObservableCollection _GameStats.Cards.Clear(); foreach (var cardGroup in loadedStats.Cards) { _GameStats.Cards.Add(cardGroup); } }
注意:确保LevelCardGroup类有公共无参构造函数,且属性可被Newtonsoft.Json正确序列化/反序列化。
方案2:保留Dictionary中转,使用安全转换
如果必须使用Dictionary,替换直接强转为Convert.ToInt32(),它能安全处理装箱的long、int甚至字符串类型的数字:
public async Task ReadGameFileInAsync(string gameVersion) { var gameSave = new Dictionary<string, object>(); if (gameVersion == "bronze") gameSave = JsonConvert.DeserializeObject<Dictionary<string, object>>(await ReadFileInAsync(BronzeGameSaveFilePath)); else if (gameVersion == "silver") gameSave = JsonConvert.DeserializeObject<Dictionary<string, object>>(await ReadFileInAsync(SilverGameSaveFilePath)); // 用Convert.ToInt32替代直接强转 _GameStats.CurrentGame = Convert.ToInt32(gameSave["CurrentGame"]); _GameStats.CurrentWord = Convert.ToInt32(gameSave["CurrentWord"]); _GameStats.Score = Convert.ToInt32(gameSave["Score"]); _GameStats.BestScore = Convert.ToInt32(gameSave["BestScore"]); _GameStats.Difficulty = Convert.ToInt32(gameSave["Difficulty"]); _GameStats.IsNewGame = (bool)gameSave["IsNewGame"]; _GameStats.IsContinue = (bool)gameSave["IsContinue"]; _GameStats.IsUnlocked = (bool)gameSave["IsUnlocked"]; _GameStats.GameVersion = (string)gameSave["GameVersion"]; // 转换List为ObservableCollection var cardList = gameSave["Cards"] as List<LevelCardGroup>; if (cardList != null) { _GameStats.Cards.Clear(); foreach (var group in cardList) { _GameStats.Cards.Add(group); } } }
额外优化:避免KeyNotFoundException
建议在读取字典值时先检查键是否存在,防止因存档缺失字段导致崩溃:
if (gameSave.TryGetValue("CurrentGame", out object currentGameObj)) { _GameStats.CurrentGame = Convert.ToInt32(currentGameObj); } else { // 使用默认值或处理缺失逻辑 _GameStats.CurrentGame = 1; }
内容的提问来源于stack exchange,提问作者ThisQRequiresASpecialist
相关产品推荐
相关产品推荐

