在反序列化JSON String期间处理名称空间更改

我有2个应用程序在redis服务器的帮助下相互通信,在我的第一个应用程序中,我能够序列化和反序列化以及以下类型的对象

{ "$type": "System.Collections.Generic.Dictionary`2[[System.Int32, mscorlib], [OPCMessagingService.Resource, OPCMessagingService]], mscorlib", "71": { "$type": "OPCMessagingService.Resource, OPCMessagingService", "SiteID": 2, "ResourceID": 71, "ProcessOrder": "001000380873", "CurrentStatus": 0, "CycleTime": 55, "DeviceList": [ { "$type": "OPCMessagingService.StackLight, OPCMessagingService", "ResourceId": 71, "DeviceIp": "10.142.117.7", "ComPort": "COM14" }, { "$type": "OPCMessagingService.LED, OPCMessagingService", "ResourceId": 71, "DeviceIp": "10.142.117.3", "ComPort": "COM10", "IsMessageDelivered": false, "RetryCount": 3, "IsRetryRequired": true, "_messageHeader": ":*HF601011471", "_messageText": "DISPOMELT 5245 BULK - 0020 -投矿物油,树脂,液体树脂和橡胶", "_delayedMessageText": "", "_counter": 0 } ], "UpdateDate": 20150120, "UpdateTime": 231506, "CurrentDate": 20150124, "CurrentTime": 151513, "CurrentMessage": "DISPOMELT 5245 BULK - 0020 -投矿物油,树脂,液体树脂和橡胶" }, "72": { "$type": "OPCMessagingService.Resource, OPCMessagingService", "SiteID": 2, "ResourceID": 72, "ProcessOrder": "001000380874", "CurrentStatus": 0, "CycleTime": 60, "DeviceList": [ { "$type": "OPCMessagingService.LED, OPCMessagingService", "ResourceId": 72, "DeviceIp": "10.142.117.98", "ComPort": "COM100", "IsMessageDelivered": false, "RetryCount": 3, "IsRetryRequired": true, "_messageHeader": ":*HF601011471", "_messageText": "DISPOMELT 5245 BULK - 0050 -熔树脂", "_delayedMessageText": "", "_counter": 0 }, { "$type": "OPCMessagingService.LED, OPCMessagingService", "ResourceId": 72, "DeviceIp": "10.142.117.4", "ComPort": "COM11", "IsMessageDelivered": false, "RetryCount": 3, "IsRetryRequired": true, "_messageHeader": ":*HF601011471", "_messageText": "DISPOMELT 5245 BULK - 0050 -熔树脂", "_delayedMessageText": "", "_counter": 0 }, { "$type": "OPCMessagingService.StackLight, OPCMessagingService", "ResourceId": 72, "DeviceIp": "10.142.117.8", "ComPort": "COM15" }, { "$type": "OPCMessagingService.StackLight, OPCMessagingService", "ResourceId": 72, "DeviceIp": "10.142.117.97", "ComPort": "COM101" } ], "UpdateDate": 20150120, "UpdateTime": 231534, "CurrentDate": 20150124, "CurrentTime": 151513, "CurrentMessage": "DISPOMELT 5245 BULK - 0050 -熔树脂" }, "73": { "$type": "OPCMessagingService.Resource, OPCMessagingService", "SiteID": 2, "ResourceID": 73, "ProcessOrder": "001000375454", "CurrentStatus": 0, "CycleTime": 60, "DeviceList": [ { "$type": "OPCMessagingService.LED, OPCMessagingService", "ResourceId": 73, "DeviceIp": "10.142.117.5", "ComPort": "COM12", "IsMessageDelivered": false, "RetryCount": 3, "IsRetryRequired": true, "_messageHeader": ":*HF601011471", "_messageText": "XHC 9228 BULK - 0050 -熔树脂", "_delayedMessageText": "", "_counter": 0 }, { "$type": "OPCMessagingService.StackLight, OPCMessagingService", "ResourceId": 73, "DeviceIp": "10.142.117.9", "ComPort": "COM16" } ], "UpdateDate": 20150120, "UpdateTime": 223043, "CurrentDate": 20150124, "CurrentTime": 151513, "CurrentMessage": "XHC 9228 BULK - 0050 -熔树脂" }, "74": { "$type": "OPCMessagingService.Resource, OPCMessagingService", "SiteID": 2, "ResourceID": 74, "ProcessOrder": "001000375455", "CurrentStatus": 0, "CycleTime": 40, "DeviceList": [ { "$type": "OPCMessagingService.LED, OPCMessagingService", "ResourceId": 74, "DeviceIp": "10.142.117.2", "ComPort": "COM9", "IsMessageDelivered": false, "RetryCount": 3, "IsRetryRequired": true, "_messageHeader": ":*HF601011471", "_messageText": "XHC 9228 BULK - 0040 -投树脂和剩料:", "_delayedMessageText": "", "_counter": 0 }, { "$type": "OPCMessagingService.StackLight, OPCMessagingService", "ResourceId": 74, "DeviceIp": "10.142.117.1", "ComPort": "COM5" } ], "UpdateDate": 20150120, "UpdateTime": 224143, "CurrentDate": 20150124, "CurrentTime": 151513, "CurrentMessage": "XHC 9228 BULK - 0040 -投树脂和剩料:" }, "75": { "$type": "OPCMessagingService.Resource, OPCMessagingService", "SiteID": 2, "ResourceID": 75, "ProcessOrder": "001000375456", "CurrentStatus": 0, "CycleTime": 50, "DeviceList": [ { "$type": "OPCMessagingService.StackLight, OPCMessagingService", "ResourceId": 75, "DeviceIp": "10.142.117.10", "ComPort": "COM17" }, { "$type": "OPCMessagingService.LED, OPCMessagingService", "ResourceId": 75, "DeviceIp": "10.142.117.6", "ComPort": "COM13", "IsMessageDelivered": false, "RetryCount": 3, "IsRetryRequired": true, "_messageHeader": ":*HF601011471", "_messageText": "XHC 9228 BULK - 0020 -投矿物油和橡胶、抗氧剂,升温", "_delayedMessageText": "", "_counter": 0 } ], "UpdateDate": 20150120, "UpdateTime": 225331, "CurrentDate": 20150124, "CurrentTime": 151513, "CurrentMessage": "XHC 9228 BULK - 0020 -投矿物油和橡胶、抗氧剂,升温" } } 

我能序列化这个并在一个应用程序中对其进行序列化,但是当我尝试在另一个显然具有不同名称空间的应用程序中对其进行序列化时。 我得到一个例外

解析JSON’System.Collections.Generic.Dictionary`2 [[System.Int32,mscorlib],[OPCMessagingService.Resource,OPCMessagingService]],mscorlib’中指定的类型时出错。 路径’$ type’,第1行,第138位。

我尝试在另一个应用程序中对Json字符串进行序列化时尝试执行以下操作,但是我无法执行其他操作来对此对象进行序列化

  public static T GetRedisKeyValue(string key) { if (key.Trim().Length > 0) { GetSentinelMaster(); using (ConnectionMultiplexer redisClient = ConnectionMultiplexer.Connect(GetRedisConfiguraion())) { IDatabase redisDB = redisClient.GetDatabase(); // Getting database connection string temp = redisDB.StringGet(key); Type type = typeof(T); JObject jsonObject = JObject.Parse(temp); jsonObject["$type"] = type.FullName + ", " + type.Assembly.FullName; // JsonConvert.DeserializeObject(temp); return JsonConvert.DeserializeObject(temp, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Objects, TypeNameAssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Full }); } } return default(T); } 

我还能做些什么来实现这一目标。

正式硬编码 "$type"的格式以包括发送系统的CLR名称空间。 所以,您可以:

  1. 重命名您的CLR名称空间以匹配发送系统的名称空间,或

  2. DefaultSerializationBinder子类化,并通过在JsonSerializerSettings.Binder设置它来在反序列化期间重命名CLR命名空间名称。

以下是第一次执行此操作:

 public class NamespaceMappingSerializationBinder : DefaultSerializationBinder { public string FromNamespace { get; set; } public string ToNamespace { get; set; } public override Type BindToType(string assemblyName, string typeName) { string fixedTypeName; if (FromNamespace != null && ToNamespace != null) { fixedTypeName = typeName.Replace(FromNamespace, ToNamespace); } else { fixedTypeName = typeName; } var type = base.BindToType(assemblyName, fixedTypeName); return type; } } 

然后,当您反序列化JSON时,在JsonSerializerSettings设置BinderJsonSerializerSettings所示:

 JsonSerializerSettings settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Objects, Binder = new NamespaceMappingSerializationBinder { FromNamespace = "From Namespace", ToNamespace = "Your Namespace" } }; 

上面解析的类型名称非常粗糙。 我在这里找到了一个更聪明的解析器: 如何解析C#generics类型名称? 。 您可能还需要扩展自定义Binder以获得映射字典。

同样,如果需要在序列化时重新映射命名空间名称,并且在.Net 4.0或更高版本中工作,则可以覆盖BindToName