You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 18:54:52