C#读取Firebase实时数据库嵌套JSON 无指定key反序列化报错
报错根因
反序列化失败的核心原因是C#实体类结构和Firebase Realtime Database返回的实际JSON结构完全不匹配:
- 你定义的
Names类将用户基础属性(Category/Status)和考勤记录属性(Date/TimeIn等)设为平级字段,但实际数据库中Users节点为三层嵌套结构:用户名key → 用户基础信息 + Date嵌套节点 → 日期字符串为key的单条考勤记录 - 你将
Date定义为string类型,但实际Date字段是一组以日期为动态key的键值对集合,Json.NET解析到Date字段后期望读取字符串值,实际碰到嵌套结构的起始标记,直接抛出类型不匹配的解析错误,也就是你看到的:
Unexpected character encountered while parsing value: [. Path '['Loubert Anne'].Date', line 1, position 40.
- 额外问题:你在遍历用户时重复发起Firebase请求拉取单个用户数据,既浪费网络开销,代码中引用的
Datas类也未定义,会触发编译错误。
修复实现
1. 定义匹配嵌套结构的实体类
删除原有结构错误的Names类,新增两个实体类对应三层数据结构:
/// <summary> /// 用户基础信息+考勤集合 /// </summary> class UserAttendance { public string Category { get; set; } public string Status { get; set; } // 对应Date节点:key为日期字符串,value为当日考勤记录 public Dictionary<string, AttendanceDetail> Date { get; set; } } /// <summary> /// 单条考勤记录详情 /// </summary> class AttendanceDetail { public string TimeIn { get; set; } public string TimeOut { get; set; } public string Duration { get; set; } public string Remarks { get; set; } }
2. 修正数据拉取与绑定逻辑
移除循环内的冗余Firebase请求,一次性拉取Users节点全量数据后本地遍历填充表格,修正后的代码如下:
private void frm_Attendance_Load(object sender, EventArgs e) { try { client = new FireSharp.FirebaseClient(fcon); // 一次性拉取所有用户数据,无需重复请求 FirebaseResponse res = client.Get("Users"); // 反序列化结构与实际嵌套格式完全匹配 Dictionary<string, UserAttendance> allUserDatas = JsonConvert.DeserializeObject<Dictionary<string, UserAttendance>>(res.Body.ToString()); PopulateDataGrid(allUserDatas); } catch (Exception ex) { // 不要空catch吞异常,保留错误信息方便调试 MessageBox.Show($"数据加载失败:{ex.Message}"); } } private void PopulateDataGrid(Dictionary<string, UserAttendance> allRecords) { dataGridView1.Rows.Clear(); dataGridView1.Columns.Clear(); // 初始化表格列 dataGridView1.Columns.Add("fullname", "FullName"); dataGridView1.Columns.Add("category", "Category"); dataGridView1.Columns.Add("date", "Date"); dataGridView1.Columns.Add("timein", "TimeIn"); dataGridView1.Columns.Add("timeout", "TimeOut"); dataGridView1.Columns.Add("duration", "Duration"); dataGridView1.Columns.Add("remarks", "Remarks"); dataGridView1.Columns.Add("status", "Status"); // 遍历所有用户 foreach (var userEntry in allRecords) { string userName = userEntry.Key; UserAttendance userInfo = userEntry.Value; // 遍历当前用户下所有日期的考勤记录 foreach (var dateEntry in userInfo.Date) { string recordDate = dateEntry.Key; AttendanceDetail detail = dateEntry.Value; // 逐行填充表格 dataGridView1.Rows.Add( userName, userInfo.Category, recordDate, detail.TimeIn, detail.TimeOut, detail.Duration, detail.Remarks, userInfo.Status ); } } }
数据库结构参考

内容的提问来源于stack exchange,提问作者Loubert Anne Espenesin
相关产品推荐
相关产品推荐

