C#后端基于dayOfAttendance动态生成指定结构JSON响应的实现
核心问题定位
- 嵌套层级冗余:当前定义的
EmployeeAttendance类是普通实体类,内部嵌套了KeyValuePairsAttendance字典属性,序列化后会在employeeAttendance节点下多出一层KeyValuePairsAttendance属性名,完全偏离目标结构中“employeeAttendance本身就是以出勤日为键的动态对象”的要求 - 实体类字段缺失:现有
Att类遗漏了目标结构里的id、qrCodeId两个必填字段,导致序列化结果缺字段 - 键值映射逻辑错位:没有直接把
dayOfAttendance的字符串值作为employeeAttendance对象的根级键,而是把值存在了字典的value对象内部
修正实现步骤
1. 调整类结构匹配目标层级
直接删除冗余的EmployeeAttendance实体类,将EmployeeAttendanceModel中EmployeeAttendance属性的类型改为键为字符串、值为考勤实体的字典类型,从根源上消除多余嵌套层。同时补全Att类缺失的字段。
2. 配置序列化规则匹配JSON格式
不管使用System.Text.Json还是Newtonsoft.Json作为序列化组件,都需要开启小驼峰属性命名策略,让C#中PascalCase格式的属性名自动转换为目标JSON要求的小驼峰格式(比如EmployeeName自动转employeeName)。枚举类型默认序列化输出整数值,刚好匹配目标中attendanceStatus的整数格式,无需额外处理。
3. 数据填充逻辑调整
遍历所有考勤记录,将每条记录的dayOfAttendance值转为字符串作为字典的键,对应的考勤实体作为值存入字典,保证键不重复。
修正后的完整代码示例
using System.Collections.Generic; namespace abc { // 通用顶层响应实体 public class ApiResponse<T> { public bool Success { get; set; } public int Code { get; set; } public T[] Data { get; set; } } // 员工维度的考勤响应实体 public class EmployeeAttendanceModel { public string EmployeeName { get; set; } // 直接将属性类型替换为字典,消除之前的冗余嵌套层 public Dictionary<string, Att> EmployeeAttendance { get; set; } } // 单条考勤记录实体 public class Att { public int Id { get; set; } // 补全缺失的id字段 public DateTime CheckInTime { get; set; } public int LateDuration { get; set; } public string EmployeeName { get; set; } public long EmployeeDeviceID { get; set; } public string QrCodeId { get; set; } // 补全缺失的qrCodeId字段 public int DayOfAttendance { get; set; } public AttendanceStatus AttendanceStatus { get; set; } } public enum AttendanceStatus { Normal = 0, Late = 1 } }
数据填充与序列化示例
// 模拟从数据库取出的员工考勤列表 var employeeName = "Zaigham"; var attendanceList = new List<Att> { new Att { Id = 2, CheckInTime = new DateTime(2021,3,3,16,48,10), LateDuration = 10, EmployeeName = employeeName, EmployeeDeviceID = 2, QrCodeId = "QRCodeID", DayOfAttendance = 3, AttendanceStatus = AttendanceStatus.Normal }, // 其他考勤记录依次添加... }; // 按dayOfAttendance构建字典,字符串形式的日期作为键 var attendanceDict = attendanceList .GroupBy(item => item.DayOfAttendance.ToString()) .ToDictionary( keySelector: group => group.Key, elementSelector: group => group.First() ); // 组装最终响应 var response = new ApiResponse<EmployeeAttendanceModel> { Success = true, Code = 200, Data = new[] { new EmployeeAttendanceModel { EmployeeName = employeeName, EmployeeAttendance = attendanceDict } } }; // 配置.NET内置System.Text.Json序列化规则 var jsonOptions = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, WriteIndented = true // 框架默认将枚举序列化为整数,匹配目标结构要求 }; var resultJson = JsonSerializer.Serialize(response, jsonOptions); // 若使用Newtonsoft.Json,对应序列化配置为: // var settings = new JsonSerializerSettings // { // ContractResolver = new CamelCasePropertyNamesContractResolver(), // Formatting = Formatting.Indented // }; // var resultJson = JsonConvert.SerializeObject(response, settings);
效果验证
执行上述代码生成的JSON结构将完全匹配目标要求,不会再出现多余的KeyValuePairsAttendance嵌套层,employeeAttendance对象下直接以"1"、"3"、"15"这类天数值作为动态键,字段名称、类型完全对齐。
内容的提问来源于stack exchange,提问作者Zaigham Raza
相关产品推荐
相关产品推荐

