如何在C#中访问API返回的嵌套JSON数据?
如何在Unity中访问动态JSON结构的日期数据?
首先,先明确你拿到的JSON结构:API返回的data里是以年份字符串为键,每个年份下又以月份字符串为键,每个月份包含两个数组:consecutive(存储连续日期的数组组,比如[[11,12],[19,20,21]]表示11-12号连续、19-21号连续)和non_consecutive(存储单个的非连续日期,比如[4]表示4号是单独的)。
看你写的代码,能发现几个关键问题,咱们一步步修正:
问题1:混合使用dynamic和JsonData,遍历年份的方式错误
你的gamePlayLogsResponse是dynamic类型,但gamePlayLogsResponse["data"]是键值对集合(键是年份字符串,比如"2019"),不能用Count加索引循环遍历。另外你初始化了JsonData gameplayLogsData却没用到,可以统一用LitJSON的JsonData来处理,类型更明确。
问题2:consecutive数组的访问索引错误
你在遍历连续日期组的时候,用了gamePlayLogsResponse["data"][...]["consecutive"][i],但i是当前组内的日期索引,正确逻辑应该是先取第z个连续组,再取组内第i个日期:consecutive[z][i]。
问题3:non_consecutive的结构理解错误
non_consecutive是一维数组(比如[4]),不是二维数组,不需要嵌套循环,直接遍历每个元素就是日期值。
问题4:日期到UI元素的索引对应问题
你的_dateItems数组应该是按日期顺序排列的(索引0对应1号,索引1对应2号...),所以日期值减1才是对应的数组索引,比如日期11对应_dateItems[10]。
修正后的完整代码
// 统一用JsonData处理,避免dynamic的不确定性 JsonData gamePlayLogsResponse = JsonMapper.ToObject(userGameLogs.downloadHandler.text); totalUnlockedLevels = 1; if (gamePlayLogsResponse["status"].ToString() == "success") { JsonData yearData = gamePlayLogsResponse["data"]; // 遍历所有年份的键(比如"2019") foreach (string yearKey in yearData.Keys) { // 只处理当前选中的年份 if (yearKey == CalendarController.year) { JsonData monthData = yearData[yearKey]; // 只处理当前选中的月份,不用遍历12个月 if (monthData.Has(CalendarController.month)) { JsonData currentMonth = monthData[CalendarController.month]; // 处理连续日期组 JsonData consecutiveGroups = currentMonth["consecutive"]; Debug.Log("连续日期组数量: " + consecutiveGroups.Count); foreach (JsonData dateGroup in consecutiveGroups) { int groupLength = dateGroup.Count; if (groupLength == 0) continue; // 跳过空数组 for (int i = 0; i < groupLength; i++) { // 把日期转成int,再减1得到UI元素的索引 int date = (int)dateGroup[i]; int itemIndex = date - 1; if (itemIndex < 0 || itemIndex >= calenderController._dateItems.Length) { Debug.LogWarning("日期" + date + "超出UI元素范围"); continue; } Image dateImage = calenderController._dateItems[itemIndex].GetComponent<Image>(); if (i == 0) { dateImage.sprite = consStartSprite; } else if (i == groupLength - 1) { dateImage.sprite = consEndSprite; } else { dateImage.sprite = consContinueSprite; } Debug.Log("设置连续日期: " + date + " -> " + calenderController._dateItems[itemIndex].name); } } // 处理非连续日期 JsonData nonConsecutiveDates = currentMonth["non_consecutive"]; Debug.Log("非连续日期数量: " + nonConsecutiveDates.Count); foreach (JsonData dateObj in nonConsecutiveDates) { int date = (int)dateObj; int itemIndex = date - 1; if (itemIndex < 0 || itemIndex >= calenderController._dateItems.Length) { Debug.LogWarning("日期" + date + "超出UI元素范围"); continue; } calenderController._dateItems[itemIndex].GetComponent<Image>().sprite = nonConsSprite; Debug.Log("设置非连续日期: " + date + " -> " + calenderController._dateItems[itemIndex].name); } } else { Debug.LogWarning("当前月份" + CalendarController.month + "没有数据"); } } } }
关键优化点说明
- 用
JsonData替代dynamic,类型更安全,避免运行时意外错误 - 直接遍历年份和月份的键,不用循环12个月,效率更高
- 增加了索引越界判断,避免数组访问报错
- 修正了连续日期组的索引访问逻辑,确保每个连续组的日期都能正确对应到UI元素
- 简化了非连续日期的处理,因为它本身就是一维数组,不需要嵌套循环
内容的提问来源于stack exchange,提问作者Imran Abbas
相关产品推荐
相关产品推荐

