如何在C#中用数组元素作为反序列化JSON的RootObject标识符?
问题:C#调用OMDB API后,无法通过字符串数组动态访问反序列化对象的属性
问题描述
我正在用C#开发一个控制台应用,调用OMDB API获取特定电影信息。把JSON反序列化为RootObject后,尝试用数组里的字段名作为标识符访问movie对象时遇到了问题。以下是我的代码:
定义的实体类
public class Rating { public string Source { get; set; } public string Value { get; set; } } public class RootObject { public string Title { get; set; } public string Year { get; set; } public string Rated { get; set; } public string Released { get; set; } public string Runtime { get; set; } public string Genre { get; set; } public string Director { get; set; } public string Writer { get; set; } public string Actors { get; set; } public string Plot { get; set; } public string Language { get; set; } public string Country { get; set; } public string Awards { get; set; } public string Poster { get; set; } public List<Rating> Ratings { get; set; } public string Metascore { get; set; } public string imdbRating { get; set; } public string imdbVotes { get; set; } public string imdbID { get; set; } public string Type { get; set; } public string DVD { get; set; } public string BoxOffice { get; set; } public string Production { get; set; } public string Website { get; set; } public string Response { get; set; } }
主程序代码
public static string getJson() { string titleOfDesiredMovie = Console.ReadLine(); WebClient client = new WebClient(); string json = client.DownloadString("http://www.omdbapi.com/?t=" + titleOfDesiredMovie + "&apikey=SECRETKEY"); return json; } static void Main(string[] args) { RootObject movie = new JavaScriptSerializer().Deserialize<RootObject>(getJson()); string[] array = { "Title", "Year", "Rated", "Genre", "Writer", "Plot" }; for (int i = 0; i < array.Length;i++ ) { foreach (var item in movie.array[i]) { Console.Write(item); } Console.WriteLine(); } var key = Console.ReadKey(); }
这是我第一次提问,若有优化提问的建议也请告知。
解决方案
你遇到的核心问题是:C#是静态类型语言,不能直接通过movie.array[i]这种字符串形式动态访问对象的属性。下面给你几种可行的解决办法:
方法1:使用反射动态获取属性值
反射可以让你在运行时获取对象的属性信息并读取值,修改你的Main方法如下:
static void Main(string[] args) { RootObject movie = new JavaScriptSerializer().Deserialize<RootObject>(getJson()); string[] array = { "Title", "Year", "Rated", "Genre", "Writer", "Plot" }; foreach (var propertyName in array) { // 获取属性信息 var property = typeof(RootObject).GetProperty(propertyName); if (property != null) { // 读取属性值并输出 var value = property.GetValue(movie); Console.WriteLine($"{propertyName}: {value ?? "N/A"}"); } else { Console.WriteLine($"{propertyName}: 属性不存在"); } } var key = Console.ReadKey(); }
方法2:改用JObject(推荐,更灵活)
如果你使用Newtonsoft.Json(NuGet包可安装),可以直接把JSON反序列化为JObject,这样就能像字典一样用字符串索引访问属性:
// 先安装Newtonsoft.Json包 using Newtonsoft.Json.Linq; static void Main(string[] args) { string json = getJson(); JObject movie = JObject.Parse(json); string[] array = { "Title", "Year", "Rated", "Genre", "Writer", "Plot" }; foreach (var propertyName in array) { var value = movie[propertyName]; Console.WriteLine($"{propertyName}: {value ?? "N/A"}"); } var key = Console.ReadKey(); }
方法3:使用ExpandoObject
JavaScriptSerializer也可以把JSON反序列化为ExpandoObject,然后转成字典来访问:
static void Main(string[] args) { dynamic movie = new JavaScriptSerializer().Deserialize<ExpandoObject>(getJson()); var movieDict = (IDictionary<string, object>)movie; string[] array = { "Title", "Year", "Rated", "Genre", "Writer", "Plot" }; foreach (var propertyName in array) { if (movieDict.TryGetValue(propertyName, out var value)) { Console.WriteLine($"{propertyName}: {value ?? "N/A"}"); } else { Console.WriteLine($"{propertyName}: 属性不存在"); } } var key = Console.ReadKey(); }
额外优化建议
- 替换过时的
WebClient:WebClient已经被标记为过时,建议改用HttpClient,它更高效且支持异步操作:
记得把Main方法改成private static readonly HttpClient _httpClient = new HttpClient(); public static async Task<string> GetJsonAsync() { string titleOfDesiredMovie = Console.ReadLine(); string url = $"http://www.omdbapi.com/?t={Uri.EscapeDataString(titleOfDesiredMovie)}&apikey=SECRETKEY"; string json = await _httpClient.GetStringAsync(url); return json; }async Task Main来支持异步。 - 不要硬编码API密钥:把API密钥放到配置文件(比如
appsettings.json)里,避免泄露和方便修改。 - 添加错误处理:比如处理网络请求失败、JSON反序列化失败、属性不存在等情况,让程序更健壮。
内容的提问来源于stack exchange,提问作者Hristo Bakardzhiev
相关产品推荐
相关产品推荐

