如何高效将含extension_前缀的JSON字段反序列化为.NET类的Dictionary属性
更优雅的解决方案:自动处理扩展字段的反序列化
嘿,你的手动遍历思路虽然可行,但确实有更简洁高效的方式——咱们可以利用Newtonsoft.Json的自定义扩展能力,在反序列化过程中自动识别extension_前缀的字段,直接存入extensions字典,不用额外写遍历逻辑。下面给你两种实用的实现方式:
方法一:自定义JsonConverter(针对性最强)
这个转换器会全程接管TargetClass的反序列化,帮你自动拆分常规字段和扩展字段:
using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; public class TargetClassConverter : JsonConverter<TargetClass> { public override TargetClass ReadJson(JsonReader reader, Type objectType, TargetClass existingValue, bool hasExistingValue, JsonSerializer serializer) { var jsonObj = JObject.Load(reader); var target = new TargetClass(); // 映射JSON里的A/B/C到类的a/b/c属性(如果需要大小写严格匹配,可以给类属性加[JsonProperty("A")]) target.a = jsonObj["A"]?.ToString(); target.b = jsonObj["B"]?.ToString(); target.c = jsonObj["C"]?.ToString(); // 自动抓取所有extension_前缀的字段存入字典 foreach (var prop in jsonObj.Properties()) { if (prop.Name.StartsWith("extension_", StringComparison.OrdinalIgnoreCase)) { target.extensions[prop.Name] = prop.Value?.ToString(); } } return target; } // 如果需要把实例序列化回JSON,这里可以实现反向逻辑(可选) public override void WriteJson(JsonWriter writer, TargetClass value, JsonSerializer serializer) { var jsonObj = new JObject(); jsonObj["A"] = value.a; jsonObj["B"] = value.b; jsonObj["C"] = value.c; foreach (var kvp in value.extensions) { jsonObj[kvp.Key] = kvp.Value; } jsonObj.WriteTo(writer); } }
怎么用?
反序列化的时候指定这个转换器就行:
var json = @"{ ""id"": ""913678a9-63d6-4261-9a4c-d710755c8141"", ""A"": null, ""B"": null, ""C"": null, ""extension_A"": ""COKOLWIEK"", ""extension_B"": ""36402User"" }"; var settings = new JsonSerializerSettings(); settings.Converters.Add(new TargetClassConverter()); var result = JsonConvert.DeserializeObject<TargetClass>(json, settings);
方法二:自定义ContractResolver(全局生效)
如果你希望这个规则能在整个项目里通用,不用每次反序列化都加转换器,可以自定义契约解析器:
using Newtonsoft.Json; using Newtonsoft.Json.Serialization; using System; using System.Reflection; public class ExtensionContractResolver : DefaultContractResolver { protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) { var prop = base.CreateProperty(member, memberSerialization); // 让extensions字典跳过常规序列化逻辑,交给我们的转换器处理 if (member.Name == nameof(TargetClass.extensions)) { prop.Ignored = true; return prop; } return prop; } protected override void ResolveContractConverter(Type objectType) { base.ResolveContractConverter(objectType); // 给TargetClass绑定我们的转换器 if (objectType == typeof(TargetClass)) { ContractConverter = new TargetClassConverter(); } } }
全局配置方式
把它设为默认设置,之后直接反序列化就行:
JsonConvert.DefaultSettings = () => new JsonSerializerSettings { ContractResolver = new ExtensionContractResolver() }; // 直接调用反序列化,不用再指定转换器 var result = JsonConvert.DeserializeObject<TargetClass>(json);
额外提示
- JSON里的
id字段你的类里没有对应属性,转换器会自动忽略它,完全符合你的需求 - 如果想让类的
a/b/c和JSON的A/B/C映射更规范,给类属性加上[JsonProperty("A")]特性就好,这样转换器里的字段名不用硬编码 - 这种方式比手动遍历更符合职责分离,逻辑集中在转换器里,后续维护也更方便
内容的提问来源于stack exchange,提问作者Kye
相关产品推荐
相关产品推荐

