如何在Newtonsoft JSON.Net反序列化前修改$type字段映射新旧类型?
解决JSON反序列化时$type类型替换的问题
我来帮你搞定这个类型映射的问题!你遇到的情况是常见的类型重构后JSON反序列化兼容问题,之前尝试JsonConverter没成功可能是没找对合适的实现方式,这里给你两种靠谱的解决方案:
方法一:使用SerializationBinder映射旧类型到新类型(推荐)
这种方式不需要修改原始JSON字符串,而是在反序列化过程中直接把旧的$type值映射到新的类型,是最优雅的长期解决方案。
实现步骤:
- 自定义一个
SerializationBinder,用来处理类型的映射逻辑:
using Newtonsoft.Json; using System; public class CustomTypeBinder : SerializationBinder { public override Type BindToType(string assemblyName, string typeName) { // 检测到旧类型名时,返回新类型 if (typeName.Equals("TestProject.Classes.TestClass", StringComparison.Ordinal)) { return typeof(TestClassNew); } // 其他类型保持原逻辑解析 return Type.GetType($"{typeName}, {assemblyName}"); } }
- 反序列化时指定这个Binder:
// 你的原始JSON字符串 string originalJson = @"[ { ""$type"": ""TestProject.Classes.TestClass, TestProject"", ""Name"": ""TestCommand"", ""Children"": [ { ""Age"": 0, ""Eta"": 8, ""Gender"": ""Ragel"" }, { ""Age"": 0, ""Eta"": 20, ""Gender"": ""Mara"" } ], ""School"": { ""Title"": ""School for Life"" } } ]"; // 配置JsonSerializerSettings var serializerSettings = new JsonSerializerSettings { // 这里要和生成原始JSON时的TypeNameHandling保持一致,比如Auto/Objects/All TypeNameHandling = TypeNameHandling.Auto, SerializationBinder = new CustomTypeBinder() }; // 直接反序列化为新类型 var result = JsonConvert.DeserializeObject<List<TestClassNew>>(originalJson, serializerSettings);
这种方法的好处是不需要改动原始JSON,所有类型映射逻辑集中在Binder里,后续如果还有其他类型变更,直接修改Binder即可。
方法二:先修改JSON中的$type值再反序列化
如果场景比较简单,也可以先手动修改JSON里的$type字段值,再进行反序列化。推荐用JToken来解析修改,比直接字符串替换更安全(避免误替换到其他字段的内容)。
实现代码:
using Newtonsoft.Json.Linq; using Newtonsoft.Json; string originalJson = @"[ { ""$type"": ""TestProject.Classes.TestClass, TestProject"", ""Name"": ""TestCommand"", ""Children"": [ { ""Age"": 0, ""Eta"": 8, ""Gender"": ""Ragel"" }, { ""Age"": 0, ""Eta"": 20, ""Gender"": ""Mara"" } ], ""School"": { ""Title"": ""School for Life"" } } ]"; // 解析JSON为JArray var jArray = JArray.Parse(originalJson); // 遍历所有对象,替换$type值 foreach (var jObj in jArray.Children<JObject>()) { if (jObj.TryGetValue("$type", out JToken typeToken)) { string oldType = typeToken.ToString(); string newType = oldType.Replace("TestProject.Classes.TestClass", "TestProject.Classes.TestClassNew"); jObj["$type"] = newType; } } // 转换为修改后的JSON字符串 string modifiedJson = jArray.ToString(); // 反序列化 var result = JsonConvert.DeserializeObject<List<TestClassNew>>(modifiedJson);
注意事项:
- 如果用直接字符串替换(比如
originalJson.Replace(...)),要确保旧类型字符串不会出现在其他字段值中,否则会导致意外修改。 - 这种方法适合临时兼容或者JSON结构非常简单的场景。
内容的提问来源于stack exchange,提问作者Karl Cassar
相关产品推荐
相关产品推荐

