{"record":{"id":"2d748df970cb3558","repo":"babalae/better-genshin-impact","slug":"repo-json-2d748d","errorCode":null,"errorMessage":"repo.json 解析失败","messagePattern":"repo\\.json 解析失败","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"BetterGenshinImpact/Core/Script/ScriptRepoUpdater.cs","lineNumber":1851,"sourceCode":"            return repoSubDir;\n        }\n        else\n        {\n            // 不存在 repo/ 目录，说明是 Git 仓库\n            return repoJsonDir;\n        }\n    }\n\n    private (string time, string url, string file) ParseJson(string jsonString)\n    {\n        var json = JObject.Parse(jsonString);\n        var time = json[\"time\"]?.ToString();\n        var url = json[\"url\"]?.ToString();\n        var file = json[\"file\"]?.ToString();\n        // 检查是否有空值\n        if (time is null || url is null || file is null)\n        {\n            throw new Exception(\"repo.json 解析失败\");\n        }\n\n        return (time, url, file);\n    }\n\n    /// <summary>\n    /// 统一的本地 zip 导入方法\n    /// 解压后自动识别仓库内容，基于目录结构重合度决定覆盖已有仓库还是创建新文件夹，\n    /// 并生成 repo_updated.json 更新标记\n    /// </summary>\n    /// <param name=\"zipFilePath\">本地 zip 文件路径</param>\n    /// <param name=\"onProgress\">进度回调 (0-100, 描述文本)</param>\n    /// <returns>导入后的仓库文件夹路径</returns>\n    public async Task<string> ImportLocalRepoZip(string zipFilePath, Action<int, string>? onProgress = null)\n    {\n        await _repoWriteLock.WaitAsync();\n        try\n        {","sourceCodeStart":1833,"sourceCodeEnd":1869,"githubUrl":"https://github.com/babalae/better-genshin-impact/blob/a7cb36712dcb409be610257d877fcea3597e9d6b/BetterGenshinImpact/Core/Script/ScriptRepoUpdater.cs#L1833-L1869","documentation":"Thrown by ParseJson when repo.json parses as valid JSON but is missing one or more required fields: 'time', 'url', or 'file'. JObject.Parse succeeds, but indexing any of those keys returns null, failing the null-check. The repo.json schema requires all three keys.","triggerScenarios":"ParseJson(jsonString) is called on repo.json content; JObject.Parse succeeds (it's valid JSON), but json[\"time\"], json[\"url\"], or json[\"file\"] is null — the key is absent, or present but null-valued in the JSON.","commonSituations":"Upstream changed the repo.json schema and dropped/renamed a field; a hand-edited repo.json is malformed; an older/newer repo version uses different field names; the JSON contains the keys but with null values.","solutions":["Open the offending repo.json and verify it contains non-null 'time', 'url', and 'file' keys.","If the schema evolved, update ParseJson to read the new field names and/or make fields optional with sensible defaults.","Before throwing, log the raw JSON and which key was missing to speed diagnosis.","Validate repo.json against a schema (or a small validator) when it's first downloaded, rejecting bad manifests early."],"exampleFix":"// before\nvar time = json[\"time\"]?.ToString();\nvar url = json[\"url\"]?.ToString();\nvar file = json[\"file\"]?.ToString();\nif (time is null || url is null || file is null)\n    throw new Exception(\"repo.json 解析失败\");\n\n// after (name the missing field)\nvar missing = new[] { \"time\", \"url\", \"file\" }.Where(k => json[k] == null || json[k]!.Type == JTokenType.Null);\nif (missing.Any())\n    throw new FormatException($\"repo.json 解析失败：缺少字段 {string.Join(\", \", missing)}\");","handlingStrategy":"validation","validationCode":"// Validate required fields with names of missing keys\nvar required = new[] { \"time\", \"url\", \"file\" };\nvar missing = required.Where(k => json[k] == null || json[k]!.Type == JTokenType.Null).ToList();\nif (missing.Count > 0)\n    throw new FormatException($\"repo.json 缺少字段: {string.Join(\", \", missing)}\");","typeGuard":"static bool IsValidRepoJson(JObject json) =>\n    json[\"time\"]?.Type == JTokenType.String &&\n    json[\"url\"]?.Type == JTokenType.String &&\n    json[\"file\"]?.Type == JTokenType.String;","tryCatchPattern":"catch (FormatException ex) when (ex.Message.Contains(\"repo.json\"))\n{\n    _logger.LogError(\"repo.json 结构变化: {Msg}\", ex.Message);\n    Toast.Error($\"仓库 manifest 格式不正确: {ex.Message}\");\n}","preventionTips":["Validate repo.json against the expected schema when downloaded.","Make ParseJson name the missing field.","Version the manifest schema if fields may evolve."],"tags":["json","newtonsoft","schema","manifest","repo-json"],"backgroundTag":null,"analyzedSha":"a7cb36712dcb409be610257d877fcea3597e9d6b","analyzedAt":"2026-08-13T16:44:57.548Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}