C#使用自定义类与Dictionary实现JSON序列化反序列化问题求助
C# JSON动态字段序列化反序列化解决方案
问题根因
你当前定义的类结构与目标JSON结构不匹配:filter_keys类将shortDescription这类动态过滤字段嵌套在properties字典节点下,但实际JSON中动态字段与notes、group等固定字段同级,没有外层properties包裹,因此反序列化无法正确映射。
解决方案:使用JsonExtensionData特性
该特性是序列化库专门为「固定字段+动态字段混合」的JSON场景设计的:
- 序列化时:字典内的键值对会自动提升到JSON根级,和固定字段平级
- 反序列化时:未匹配到固定字段的键值对会自动存入该字典
你只需给properties字段添加对应序列化库的特性即可,调整后的类结构如下:
using System.Collections.Generic; // 使用System.Text.Json的话引入下面的命名空间 using System.Text.Json.Serialization; // 使用Newtonsoft.Json的话引入下面的命名空间 // using Newtonsoft.Json; public class filter_keys { public string notes { get; set; } public string group { get; set; } public string assigned { get; set; } // System.Text.Json的特性 [JsonExtensionData] // Newtonsoft.Json的特性 // [JsonExtensionData] public Dictionary<string, filter_properties> properties { get; set; } = new Dictionary<string, filter_properties>(); } public class filter_properties { public bool contains { get; set; } public bool equals { get; set; } public bool startsWith { get; set; } public string value { get; set; } }
可选优化:添加便捷访问属性
如果需要直接通过点语法访问shortDescription、description这类常用字段,不需要每次查字典,可以给filter_keys加两个计算属性,不影响序列化反序列化结果:
public class filter_keys { public string notes { get; set; } public string group { get; set; } public string assigned { get; set; } [JsonExtensionData] public Dictionary<string, filter_properties> properties { get; set; } = new Dictionary<string, filter_properties>(); // 便捷访问shortDescription,不存在返回null public filter_properties shortDescription { get => properties.TryGetValue(nameof(shortDescription), out var prop) ? prop : null; set => properties[nameof(shortDescription)] = value; } // 便捷访问description,不存在返回null public filter_properties description { get => properties.TryGetValue(nameof(description), out var prop) ? prop : null; set => properties[nameof(description)] = value; } }
使用示例
构造并序列化对象
var filter = new filter_keys { notes = "Something bad happened", group = "some group", assigned = "to me", // 直接给便捷属性赋值 shortDescription = new filter_properties { startsWith = true, value = "some text" }, description = new filter_properties { contains = true, value = "some more text" } }; // 手动添加其他动态字段 filter.properties.Add("createdAfter", new filter_properties { value = "2021-08-17" }); // System.Text.Json序列化 string json = JsonSerializer.Serialize(filter, new JsonSerializerOptions { WriteIndented = true }); // Newtonsoft.Json序列化 // string json = JsonConvert.SerializeObject(filter, Formatting.Indented);
输出的JSON结构和你给出的示例完全一致。
反序列化并访问属性
// System.Text.Json反序列化 filter_keys filterObj = JsonSerializer.Deserialize<filter_keys>(json); // Newtonsoft.Json反序列化 // filter_keys filterObj = JsonConvert.DeserializeObject<filter_keys>(json); // 校验shortDescription是否存在并访问子属性 if (filterObj.shortDescription != null) { bool isStartsWith = filterObj.shortDescription.startsWith; string descValue = filterObj.shortDescription.value; } // 校验任意动态字段是否存在 if (filterObj.properties.TryGetValue("createdAfter", out var createdProp)) { string dateValue = createdProp.value; }
内容的提问来源于stack exchange,提问作者Autonomic
相关产品推荐
相关产品推荐

