C#使用Newtonsoft.Json解析JSON的筛选与数据提取问题
解决Newtonsoft.Json遍历多语言配置并筛选特定键的问题
我明白你遇到的困扰了——用dynamic解析JSON后,直接遍历languages时没搞清楚遍历对象的类型,导致拿不到键名还访问data报错。咱们一步步来解决:
问题根源
当你用JsonConvert.DeserializeObject返回dynamic时,json_obj.languages实际上是Newtonsoft.Json里的JObject类型。foreach遍历它的时候,拿到的不是直接的语言对象,而是JProperty类型的键值对——每个JProperty包含了键名(比如ja_lang)和对应的语言对象值。所以你之前直接访问language.data肯定会报错,因为language是键值对,不是语言对象本身。
修正后的代码(dynamic方式)
调整遍历逻辑,先判断键名,再获取对应的语言对象:
string jsonString = @"{""languages"": { ""ja_lang"": { ""data"": { ""name"": ""Japanese"" }, ""files"": [[""ja"", ""Japanese File"", ""lang_ja.txt""]] }, ""en_lang"": { ""data"": { ""name"": ""English"" }, ""files"": [[""en"", ""English File"", ""lang_en.txt""]] } } }"; dynamic jsonObj = JsonConvert.DeserializeObject(jsonString); // 遍历languages下的每个键值对 foreach (JProperty langProperty in jsonObj.languages) { // 筛选键名以"ja_"开头的项 if (!langProperty.Name.StartsWith("ja_")) continue; // 获取对应的语言对象 dynamic langObj = langProperty.Value; // 提取data中的name string name = langObj.data.name; // 提取files里的文件名(注意files是二维数组,取第一个子数组的第三个元素) string fileName = langObj.files[0][2]; Console.WriteLine($"名称: {name}, 文件名: {fileName}"); }
更规范的强类型方式(推荐)
如果项目规模较大,用强类型模型会更安全,避免dynamic的隐式类型问题。先定义对应的类:
public class LanguageData { public string Name { get; set; } } public class LanguageConfig { public LanguageData Data { get; set; } public List<List<string>> Files { get; set; } } public class RootConfig { public Dictionary<string, LanguageConfig> Languages { get; set; } }
然后解析并处理:
RootConfig root = JsonConvert.DeserializeObject<RootConfig>(jsonString); foreach (var kvp in root.Languages) { if (!kvp.Key.StartsWith("ja_")) continue; string name = kvp.Value.Data.Name; string fileName = kvp.Value.Files[0][2]; Console.WriteLine($"名称: {name}, 文件名: {fileName}"); }
这样代码的可读性和安全性都更高,也不容易出现类型访问错误。
内容的提问来源于stack exchange,提问作者anon
相关产品推荐
相关产品推荐

