如何将API返回的带编号属性的JSON反序列化为C# Ticket对象?
优化JSON到C# Ticket类的反序列化方案
针对你遇到的JSON结构与目标C#类不匹配的问题,推荐使用自定义JSON转换器的方案,比手动遍历字典更优雅且易维护,下面给出两种主流JSON库的实现方式:
方案一:使用Newtonsoft.Json(Json.NET)
步骤1:定义匹配JSON结构的中间类
先定义能直接映射原始JSON的临时类,用于承接反序列化的中间结果:
// 单个字段的结构 public class TicketField { public string DisplayName { get; set; } public object Value { get; set; } } // 外层包裹类 public class TicketWrapper { public Dictionary<string, TicketField> Ticket { get; set; } }
步骤2:编写自定义转换器
实现JsonConverter<Ticket>,将中间结构转换为目标Ticket类:
public class TicketConverter : JsonConverter<Ticket> { // 提前配置DisplayName到属性的映射逻辑,避免硬编码switch private static readonly Dictionary<string, Action<Ticket, object>> _fieldMappings = new() { {"Ticket ID", (ticket, val) => ticket.TicketID = Convert.ToInt32(val)}, {"Last Modified", (ticket, val) => ticket.LastModified = DateTime.Parse((string)val)}, {"Last User", (ticket, val) => ticket.LastUser = (string)val}, {"Seq_Group", (ticket, val) => ticket.Seq_Group = Convert.ToInt32(val)} // 新增字段只需在这里添加映射项 }; public override Ticket ReadJson(JsonReader reader, Type objectType, Ticket existingValue, bool hasExistingValue, JsonSerializer serializer) { // 先反序列化为中间类 var wrapper = serializer.Deserialize<TicketWrapper>(reader); var ticket = new Ticket(); // 遍历字段并应用映射 foreach (var field in wrapper.Ticket.Values) { if (_fieldMappings.TryGetValue(field.DisplayName, out var setProperty)) { setProperty(ticket, field.Value); } } return ticket; } // 如果不需要将Ticket序列化为原始JSON格式,可暂不实现WriteJson public override void WriteJson(JsonWriter writer, Ticket value, JsonSerializer serializer) { throw new NotImplementedException(); } }
步骤3:使用转换器反序列化
string json = "你的API返回JSON字符串"; Ticket ticket = JsonConvert.DeserializeObject<Ticket>(json, new TicketConverter());
方案二:使用System.Text.Json(.NET Core/.NET 5+内置)
如果使用官方内置的JSON库,实现逻辑类似:
步骤1:定义中间类
注意Value用JsonElement类型兼容不同数据类型:
public class TicketField { public string DisplayName { get; set; } public JsonElement Value { get; set; } } public class TicketWrapper { public Dictionary<string, TicketField> Ticket { get; set; } }
步骤2:编写自定义转换器
public class TicketConverter : JsonConverter<Ticket> { private static readonly Dictionary<string, Action<Ticket, JsonElement>> _fieldMappings = new() { {"Ticket ID", (ticket, val) => ticket.TicketID = val.GetInt32()}, {"Last Modified", (ticket, val) => ticket.LastModified = val.GetDateTime()}, {"Last User", (ticket, val) => ticket.LastUser = val.GetString()}, {"Seq_Group", (ticket, val) => ticket.Seq_Group = val.GetInt32()} }; public override Ticket Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { var wrapper = JsonSerializer.Deserialize<TicketWrapper>(ref reader, options); var ticket = new Ticket(); foreach (var field in wrapper.Ticket.Values) { if (_fieldMappings.TryGetValue(field.DisplayName, out var setProperty)) { setProperty(ticket, field.Value); } } return ticket; } public override void Write(Utf8JsonWriter writer, Ticket value, JsonSerializerOptions options) { throw new NotImplementedException(); } }
步骤3:使用转换器反序列化
string json = "你的API返回JSON字符串"; var options = new JsonSerializerOptions(); options.Converters.Add(new TicketConverter()); Ticket ticket = JsonSerializer.Deserialize<Ticket>(json, options);
方案优势
- 代码结构清晰,新增字段只需更新映射字典,无需修改核心逻辑
- 避免大量重复的分支判断,可维护性更高
- 符合JSON库的扩展规范,逻辑更贴合序列化/反序列化的流程
内容的提问来源于stack exchange,提问作者Rick Wolff
相关产品推荐
相关产品推荐

