在 JSON 字符串反序列化期间处理名称空间更改 [英] handling name space changes during deserialization of JSON String
问题描述
我有 2 个应用程序在 redis 服务器的帮助下相互通信,在我的第一个应用程序中,我能够序列化和反序列化以下类型的对象
I have 2 applications that are communicate amongst each other with the help of a redis Server, In my first application i am able to serialize and de serialize and object of the following type
{
"$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 -投矿物油和橡胶、抗氧剂,升温"
}
}
我可以在一个应用程序中对其进行序列化和反序列化,但是当我尝试在另一个显然具有不同名称空间的应用程序中对其进行反序列化时.我得到一个例外
I able serialize this and de serialize this in one application but when i try to de serialize this in another application which obviously has a different name space. and i get an exception
JSON 'System.Collections.Generic.Dictionary`2[[System.Int32, mscorlib],[OPCMessagingService.Resource, OPCMessagingService]], mscorlib'中指定的错误解析类型.路径$type",第 1 行,位置 138.
Error resolving type specified in JSON 'System.Collections.Generic.Dictionary`2[[System.Int32, mscorlib],[OPCMessagingService.Resource, OPCMessagingService]], mscorlib'. Path '$type', line 1, position 138.
我尝试在另一个应用程序中反序列化 Json 字符串时执行以下操作,但它不起作用我还能做什么来反序列化此对象
I have tried to do the following while de serializing the Json String in another application and it does not work what else can i do to de serialize this object
public static T GetRedisKeyValue<T>(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<T>(temp);
return JsonConvert.DeserializeObject<T>(temp, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Objects, TypeNameAssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Full });
}
}
return default(T);
}
我还能做些什么来实现这一目标.
What else can i do to achieve this.?
推荐答案
"$type"
的格式正式为 硬编码 以包含发送系统的 CLR 命名空间.因此,您可以:
The format of the "$type"
is officially hardcoded to include the CLR namespace of the sending system. So, you can either:
重命名 CLR 命名空间以匹配发送系统的命名空间,或
Rename your CLR namespaces to match those of the sending system, or
子类 DefaultSerializationBinder
并使用它在反序列化过程中重命名 CLR 命名空间名称,方法是在 JsonSerializerSettings.Binder
.
以下是这样做的第一步:
The following is a first cut at doing this:
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
中设置 Binder
:
Then, when you deserialize your JSON, set the Binder
in the JsonSerializerSettings
like so:
JsonSerializerSettings settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Objects, Binder = new NamespaceMappingSerializationBinder { FromNamespace = "From Namespace", ToNamespace = "Your Namespace" } };
上面的类型名解析极其粗糙.我在这里找到了一个更智能的解析器:How to parse C# generic type names?.您可能还需要扩展自定义 Binder
以获得映射字典.
The type name parsing in the above is extremely crude. I found a much smarter parser here: How to parse C# generic type names?. You might also need to extend the custom Binder
to have a dictionary of mappings.
同样,如果您需要在序列化时重新映射命名空间名称,并且在 .Net 4.0 或更高版本中工作,您可以覆盖 BindToName
.
Similarly, if you need to remap the namespace names on serialization, and are working in .Net 4.0 or above, you can override BindToName
.
这篇关于在 JSON 字符串反序列化期间处理名称空间更改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!