C# .NET7中SteamAPI响应反序列化返回Null问题排查
问题:.NET 7中反序列化Steam API响应时SteamAppList.Applist始终为Null
在.NET 7环境下,通过RestSharp请求Steam的GetAppList API并保存响应到文件后,加载文件反序列化时,SteamAppList.Applist始终为Null。已尝试用Json2Csharp、JetBrains Rider生成数据模型,调整多种JsonSerializerOptions配置,调试后问题仍存在。
相关代码与数据
数据模型(SteamAppList.cs)
[Serializable] public class SteamAppList { [JsonPropertyName("applist")] public Applist Applist; } [Serializable] public class Applist { [JsonPropertyName("apps")] public List<App> Apps; } [Serializable] public class App { [JsonPropertyName("appid")] public int Appid; [JsonPropertyName("name")] public string Name; }
请求与反序列化逻辑(SteamApps.cs)
public class SteamApps { private readonly CancellationToken cancellationToken; private async Task<RestResponse> GetSteamApps() { var client = new RestClient(); var request = new RestRequest("https://api.steampowered.com/ISteamApps/GetAppList/v2/"); request.AddHeader("Accept", "*/*"); request.AddHeader("User-Agent", "Major GSM"); var response = await client.GetAsync(request, cancellationToken); return response; } public bool RetireveAndSaveSteamApps() { var path = FileModule.GetDirectoryPath(MajorGsmLibrary.ApplicationDirectory.Games); var fileName = "steam.library.json"; RestResponse restResponse = GetSteamApps().Result; try { File.WriteAllText(Path.Combine(path, fileName), restResponse.Content); } catch (IOException exception) { LogModule.WriteError("Could not write steam library file!", exception); return false; } catch (ArgumentNullException exception) { LogModule.WriteError("Missing data for steam library file", exception); return false; } return true; } public static string CheckGameAgainstSteamLibraryWithAppId(string appId) { var path = FileModule.GetDirectoryPath(MajorGsmLibrary.ApplicationDirectory.Games); var fileName = "steam.library.json"; var fileData = File.ReadAllText(Path.Combine(path, fileName)); SteamAppList? steamAppList = JsonSerializer.Deserialize<SteamAppList>(fileData, new JsonSerializerOptions { MaxDepth = 64, Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping }); if (steamAppList!.Applist != null) { var app = steamAppList.Applist.Apps.SingleOrDefault(x => x.Appid.ToString() == appId); if (app != null) return app.Name; } return "Unknown"; } }
调用代码
foreach (var game in Games) { var appName = SteamApps.CheckGameAgainstSteamLibraryWithAppId(game.AppId); if (appName == "Unknown") return; game.FoundInSteamLibrary = true; game.SteamLibraryName = appName; }
收到的JSON响应示例
{ "applist": { "apps": [ { "appid": 1941401, "name": "" }, { "appid": 1897482, "name": "" }, { "appid": 2112761, "name": "" }, { "appid": 1470110, "name": "Who's Your Daddy Playtest" }, { "appid": 2340170, "name": "Melon Knight" }, { "appid": 1793090, "name": "Blockbuster Inc." } ] } }
解决方案
问题核心:System.Text.Json默认只序列化/反序列化类的属性(Property),不处理字段(Field),而当前模型中定义的都是字段,导致反序列化时无法映射数据。
方法1:将模型中的字段改为属性
修改模型,把字段替换为带get/set的属性,并可移除不必要的[Serializable]标记(该标记用于二进制序列化,System.Text.Json不需要):
public class SteamAppList { [JsonPropertyName("applist")] public Applist? Applist { get; set; } } public class Applist { [JsonPropertyName("apps")] public List<App>? Apps { get; set; } } public class App { [JsonPropertyName("appid")] public int Appid { get; set; } [JsonPropertyName("name")] public string? Name { get; set; } }
方法2:配置JsonSerializerOptions包含字段
如果不想修改模型,在反序列化时添加IncludeFields = true配置:
SteamAppList? steamAppList = JsonSerializer.Deserialize<SteamAppList>(fileData, new JsonSerializerOptions { MaxDepth = 64, Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, IncludeFields = true // 启用字段反序列化 });
额外优化建议
- 在
RetireveAndSaveSteamApps方法中,使用GetSteamApps().Result可能导致异步死锁,建议将方法改为异步并使用await:public async Task<bool> RetireveAndSaveSteamApps() { var path = FileModule.GetDirectoryPath(MajorGsmLibrary.ApplicationDirectory.Games); var fileName = "steam.library.json"; RestResponse restResponse = await GetSteamApps(); // 后续逻辑不变 } - 模型中使用可空类型(如
Applist?、List<App>?),避免空引用异常。
内容的提问来源于stack exchange,提问作者MrSourceSys
相关产品推荐
相关产品推荐

