ASP.NET中从外部API筛选国家法定假日数据及JArray索引异常排查
解决异常并实现国家法定假日筛选功能
首先,咱们先拆解你遇到的问题:
异常原因分析
你看到的ArgumentException是因为API返回的是JSON数组(用[]包裹),反序列化后的content是JArray类型,但你试图用访问JObject属性的方式(content["HolidayCaption"])去读取它,这完全不符合JArray的访问规则——JArray只能通过索引(比如content[0])或者遍历元素来访问内容。另外,代码里的SelectTokens("aa")是无意义的,API返回的结构里根本没有aa这个路径,这也会导致你拿不到任何数据。
分步解决方案
1. 修正数据解析逻辑,加入筛选条件
我们需要遍历返回的JSON数组,筛选出is_national_holiday == true的记录,同时修正模型的使用逻辑:
修正后的Repository代码
using Newtonsoft.Json; using Newtonsoft.Json.Linq; using RestSharp; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; public async Task<HoliDate> GetHolidaysAsync() { var client = new RestClient("https://api-harilibur.vercel.app/api"); var request = new RestRequest(Method.GET); // 注意:原代码里的APIKey头是"Application/Json",这看起来不太对,如果API需要合法的Key请替换成正确值 // client.AddHeader("APIKey", "YourValidAPIKeyHere"); var response = await client.ExecuteAsync(request); if (response.IsSuccessful && !string.IsNullOrEmpty(response.Content)) { // 因为返回的是数组,直接反序列化为JArray var holidayArray = JArray.Parse(response.Content); // 筛选国家法定假日,同时映射到Holiday模型 var nationalHolidays = holidayArray .Cast<JObject>() .Where(holiday => holiday["is_national_holiday"]?.Value<bool>() == true) .Select(holiday => new Holiday { holiday_date = holiday["holiday_date"]?.Value<DateTime>() ?? DateTime.MinValue, holiday_name = holiday["holiday_name"]?.Value<string>() ?? string.Empty, is_national_holiday = true // 已经筛选过,直接设为true即可 }) .ToList(); // 返回包装后的模型,如果不需要HolidayCaption可以考虑移除该字段 return new HoliDate { // 如果需要HolidayCaption,可以设置为第一个假日的日期,或者年度(比如DateTime.Now.Year) HolidayCaption = nationalHolidays.FirstOrDefault()?.holiday_date ?? DateTime.MinValue, Holiday = nationalHolidays }; } // 打印错误信息便于调试 System.Console.WriteLine($"请求失败或无内容:{response.Content}"); return null; }
2. 修正模型(可选优化)
原模型里的HolidayCaption字段在API返回中不存在,如果你不需要这个字段,可以直接简化模型,或者明确它的用途(比如表示年度):
public class HoliDate { // 如果不需要可以删除这个字段 public DateTime HolidayCaption { get; set; } public IEnumerable<Holiday> Holiday { get; set; } } public class Holiday { public DateTime holiday_date { get; set; } public string holiday_name { get; set; } public bool is_national_holiday { get; set; } }
3. Controller代码保持不变(可加空列表判断)
如果筛选后没有国家法定假日,nationalHolidays会是空列表,你可以在Controller里补充判断:
[Route("Holiday")] [HttpGet] public async Task<IActionResult> GetByIdAsync() { var model = await repository.GetHolidaysAsync(); if (model == null) return NotFound("获取假日数据失败"); if (!model.Holiday.Any()) return Ok(new { Message = "当前没有国家法定假日记录" }); return Ok(model); }
额外优化建议
- 不要重复创建HttpClient/RestClient:每次请求都新建客户端会消耗不必要的资源,建议将RestClient注册为单例(在ASP.NET Core中可以用
services.AddSingleton<RestClient>())。 - 异常处理增强:可以捕获反序列化过程中的异常,比如
JsonException,避免程序崩溃。 - API头修正:原代码里的
http.DefaultRequestHeaders.Add("APIKey", "Application/Json")看起来很奇怪,Application/Json是Content-Type的常用值,不是APIKey,如果该API需要认证,请替换为正确的API密钥。
内容的提问来源于stack exchange,提问作者besok uas
相关产品推荐
相关产品推荐

