在JSON字符串反序列化期间处理名称空间更改

在JSON字符串反序列化期间处理名称空间更改

本文介绍了在JSON字符串反序列化期间处理名称空间更改的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有2个应用程序在redis Server的帮助下相互通信,在我的第一个应用程序中,我可以序列化和反序列化,并且可以使用以下类型的对象

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 String时,我尝试执行以下操作,但我不能采取其他措施来反序列化此对象

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);
    }

我还能做些什么??

推荐答案

"$type"的格式正式为经过硬编码以包含发送系统的CLR名称空间.因此,您可以:

The format of the "$type" is officially hardcoded to include the CLR namespace of the sending system. So, you can either:

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

  1. Rename your CLR namespaces to match those of the sending system, or

DefaultSerializationBinder 的子类化并用于通过在 JsonSerializerSettings.Binder 中进行设置,可以在反序列化期间重命名CLR名称空间名称. .

Subclass the DefaultSerializationBinder and use it to rename the CLR namespace names during deserialization by setting it in the 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" } };

上面的类型名称解析非常粗糙.我在这里找到了更聪明的解析器:如何解析C#泛型类型名称? .您可能还需要扩展自定义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字符串反序列化期间处理名称空间更改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-07 03:58