当前位置: 首页 > news >正文

解决一个C# 在Framework 4.5反序列化的问题

概要

本文解决一个运行在Framework 4.5的旧系统,在作Change时候遇到的兼容性问题。原有的JSON结果发生了变化,但是在解析和反序列化的时候,需要同时兼容新旧JSON格式。

问题提出

随着JSON的格式发生变化,类的定义也要发生变化,具体如下:
原有的JSON格式如下:

{"Name": "John","Age"": 20,"Scores"": [90, 85, 88],"Details"": {"grade": 10, "school": "High School"},"Address": {"City": "New York", "Region":"ABC"}
}

新的JSON格式:

{"Name": "John","Age"": 20,"Scores"": [90, 85, 88],"Details"": {"grade": 10, "school": "High School"},"Address": {"City": "New York", "Region": {""Code"":"111",""Name"": "GGG"}
}

原有的Address类定义如下:

 [DataContract]public class Address{[DataMember]public string City { get; set; }}
[DataContract]
public class AddressV0 : Address
{[DataMember]public Region Region { get; set; }
}

随着Address的结果发生变化,但是新旧格式都要支持,所以增加AddressV1类,重新定义Region。

[DataContract]
public class AddressV1 : Address
{[DataMember]public Region Region { get; set; }
}
[DataContract]
public class Region
{[DataMember]public string Name { get; set; }[DataMember]public string Code { get; set; }
}

因为要同时支持AddressV1的结构和AddressV0的结构,所以在Student类中新增AddressV1字段

[DataContract]
public class Student
{[DataMember]public AddressV0 Address { get; set; }[DataMember]public AddressV1 AddressV1 { get; set; }
}

但是新的JSON格式中地址字段的名称是Address,并不是AddressV1,所以无法直接反序列成需要的对象。

另一个限制是现有的反序列方式是通过System.Runtime.Serialization的库完成,虽然功能有限,但是考虑到系统的稳定运行要求,不能因为这次的change,更换成Newtonsoft等当前流行的代码库。

解决方法

使用OnDeserialized属性,该属性是一个方法,这个方法在反序列完成后触发。因此,先把Address和AddressV1 对象从自动反序列话改成手动反序列化,代码如下:

[DataContract]
public class Student
{[IgnoreDataMember]public AddressV0 Address { get; set; }[IgnoreDataMember]public AddressV1 AddressV1 { get; set; }
}

我们使用OnDeserialized定制反序列话过程,需要原始的JSON字符串。但是很遗憾,该方法虽然有一个StreamingContext参数,但是现有系统使用的是Framework 4.5,StreamingContext并不包含原始的JSON字符串。

解决方法是在Student定义一个静态字段originalString,每次反序列之前,手动传入原始的JSON字符串,并且该字段不出现在对Student对象序列化时候的字符串中。代码如下:

[DataContract]
public class Student
{[IgnoreDataMember]public AddressV0 Address { get; set; }[IgnoreDataMember]public AddressV1 AddressV1 { get; set; }[IgnoreDataMember]public static string originalString = string.Empty;
}

这样我们在Student中,重新定义OnDeserialized方法,在该方法中,根据原始JSON字符串判断是要反序列化AddressV0 对象还是AddressV1 对象。

[DataContract]
public class Student
{[IgnoreDataMember]public AddressV0 Address { get; set; }[IgnoreDataMember]public AddressV1 AddressV1 { get; set; }[IgnoreDataMember]public static string originalString = string.Empty;[OnDeserialized]private void OnDeserialized(StreamingContext context){if (Student.originalString == string.Empty){return;}JObject obj = JObject.Parse(Student.originalString);var addressToken = obj.SelectToken("Address");var regionToken = addressToken?.SelectToken("Region");var serializer = new DataContractJsonSerializer(typeof(AddressV0));using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(addressToken!.ToString()))){if (regionToken?.Type == JTokenType.Object){serializer = new DataContractJsonSerializer(typeof(AddressV1));this.AddressV1 = serializer.ReadObject(ms) as AddressV1 ;return;}this.Address = serializer.ReadObject(ms) as AddressV0;return;}   }
}

具体的判断方法,采用Newtonsoft库的JObject 和JToken,因为它们可以精确的判断Region字段是字符串还是对象,最后生成对象,还是使用DataContractJsonSerializer进行反序列化,和系统原有的方式一致,避免造成兼容问题。

结论

在旧系统做change时候,需要按照修旧如旧的原则。如果change涉及主流程的修改,更应该小心,我们可以时候第三方库作为辅助,但是不能直接应用,避免产生各种兼容性问题。

http://www.dtcms.com/a/435514.html

相关文章:

  • 营销导向网站建设流程电脑配件网站建设
  • 网站搭建素材群会计培训班的费用是多少
  • 建设银行短信带网站江苏省住房和城乡建设厅网站首页
  • 哪个网站最好wordpress找回密码收不到邮件
  • 哈希表(散列表)介绍及实现
  • 一个专门做ppt的网站吗注册域名需要实名认证吗
  • 做网站外包工作怎么样visual composer for wordpress
  • 平面设计鉴赏网站关于加强网站建设
  • Spring Boot 热部署配置
  • 成都网站设计公司南宁seo按天收费
  • 自适应微网站开发专业集团门户网站建设企业
  • PCIe协议之低功耗篇之 理论深度学习(三)
  • 广州帮人网站建设广州网站建设需要多少费用
  • 在县城怎么做网站公司网络域名侵权十大案例
  • 佛山专业做淘宝网站推广住房与城乡建设局网站
  • 康复实训室介绍:告别“假人”模型,在沉浸式环境中锻造康复精英的黄埔军校
  • C语言小白实现多功能计算器的艰难历程
  • 【C++实战(62)】从0到1:C++打造TCP网络通信实战指南
  • 企业网站建设杭州公司宠物寄养网站毕业设计
  • 同ip怎么做不同的网站网站设计需要什么技术
  • 邢台做wap网站的公司做旅行路线的网站
  • 港口备案怎么在网站做培训心得简短
  • 菏泽市住房和建设局网站专业建站公司电话咨询
  • 网站关键词几个字网站建设策划书范文提纲
  • Java 大视界 -- Java 大数据在智能安防周界防范系统中的行为分析与预警精度提升(419)
  • 北京金港建设股份有限公司网站wordpress怎么迁移到空间
  • 查工作单位的网站长沙网站建设公司有哪些
  • 淄博网站制作建设wordpress添加微信公众号
  • 【C++实战(63)】C++ 网络编程实战:UDP客户端与服务端的奥秘之旅
  • [数据分享第八弹]历史人文相关地理数据