巧用 JSON序列化/反序列化,轻松实现C#对象映射
当前位置:点晴教程→知识管理交流
→『 技术文档交流 』
一、引言简述在 C#编程的世界里,对象映射是一项十分重要且常用的操作,而利用JSON序列化/反序列化来实现对象映射更是有着广泛的应用场景。比如说,当我们需要与外部系统进行数据交互时,常常要把C#中的对象转换为JSON格式的数据发送出去,这就涉及到对象的序列化;而接收到外部传来的JSON数据后,又需要将其还原成C#对象以便后续处理,这就是反序列化的过程了。再比如,在存储数据或者对数据进行传输封装等操作时,这种基于JSON的对象映射方式也能帮我们更便捷地处理数据。 今天,我就来给大家详细分享一下利用 JSON序列化/反序列化轻松实现对象映射的具体步骤,相信掌握了这些内容,会让大家在面对相关开发需求时更加得心应手,下面咱们就正式开始吧。 二、JSON序列化/反序列化基础知识JSON数据格式简介JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它基于JavaScript编程语言的一个子集,但因其文本格式清晰简洁,被广泛用于数据交换和存储。 JSON所支持的数据结构及常见表现形式如下: •对象(Object):对象是由键值对组成的无序集合,键是字符串,值可以是任何类型,包括对象和数组。对象由一对花括号{ } 包围,键和值之间用冒号: 分隔,键值对之间用逗号, 分隔。例如:{"name": "John Doe", "age": 30, "isMarried": false, "children": ["Alice", "Bob"]}。需要注意的是,JSON中对象的属性名必须用双引号,属性值如果是字符串也必须用双引号,只要涉及到字符串,就必须使用双引号,并且不支持undefined。 •数组(Array):数组是值的有序集合,每个值可以是任何类型,包括对象和数组。数组由一对方括号[ ] 包裹,值之间用逗号, 分隔。比如:["apple", "banana", "cherry"]。 •字符串(String):JSON字符串是由双引号" " 包围的 Unicode字符序列,使用反斜杠\ 转义,像{"name": "Apifox", "city": "Guangzhou"} 中的"name" 和"city" 就是字符串的示例。 •数字(Number):可以是整数或浮点数,例如{"age": 30, "weight": 65.5} 中的30 和65.5 分别是整数和浮点数,数字不需要双引号包围。 •布尔值(Boolean):只有两个取值,即true 和false,如{"isStudent": true, "isEmployed": false} 中的isStudent 和isEmployed 取值示例,同样不需要双引号包围。 •null:表示一个空值,像{"middleName": null} 里的middleName 的值就是null,也无需双引号包围。 这些结构还可以相互嵌套,形成复杂的 JSON数据格式,以此来满足不同场景下的数据表示需求。 C#中相关命名空间及类库介绍在 C#里,常用于JSON序列化/反序列化操作的有以下几个重要的命名空间及对应的类库: 1.System.Web.Script.Serialization: 这个命名空间下的JavaScriptSerializer 类可用于 JSON的序列化和反序列化。例如,以下是简单的代码示例展示其使用方式:
不过,该类在处理DateTime 类型数据的序列化时可能存在一些小问题,比如序列化后的时间可能会出现偏差等情况。 2.Newtonsoft.Json(JSON.NET): 这是一个成熟且使用广泛的第三方库,拥有丰富的功能和强大的灵活性,多年来在.NET社区中被广泛接受和使用。它支持弱类型转换,并且提供了一些更高级的功能,比如完全自定义的序列化和反序列化逻辑,能处理循环引用、自定义转换器、忽略属性等等,可以方便地应对一些复杂的JSON数据场景。使用前需要通过NuGet进行安装,示例代码如下:
3.System.Text.Json: 它是.NET Core的一部分,在创建跨平台应用程序时,不需要额外的依赖项,使用起来较为方便。并且在性能方面进行了优化,通常比Newtonsoft.Json 更快,利用了新的读写 API,采用更高效的内部实现,提供了更好的性能和内存利用率。同时,它还提供了一些简化的API,在处理简单的JSON数据时更容易操作,不过默认是强类型转换,比如实体类定义的是字符串,JSON字符串返回的是整型,转换时会报错。示例代码如下:
开发者可以根据具体的项目需求、数据复杂程度以及性能等方面的考量,来选择合适的命名空间及类库进行 JSON序列化/反序列化操作。 三、利用 System.Runtime.Serialization.Json实现对象映射类的准备与标记当我们使用System.Runtime.Serialization.Json 这个命名空间来进行对象映射相关操作时,有个重要的前提要求,那就是参与序列化和反序列化的类需要进行特定的标记。 具体来说,类需要标记为[DataContract],它相当于一种契约,是使用DataContractJsonSerializer 序列化和反序列化必须要添加的标识。而对应类中的属性,则要标记为[DataMember],只有标记了的属性才会参与到序列化和反序列化的过程当中。 以下面这个简单的Student 类为例来看看具体如何标记:
在上述代码中,Student 类标记了[DataContract],其内部的ID、Name、Age、Sex 这几个属性都标记了[DataMember],这样在后续利用System.Runtime.Serialization.Json 相关功能时,这个类的对象就可以顺利地进行序列化和反序列化操作了,将类和属性按照这样的要求标记好,是利用该方式实现对象映射的基础准备工作哦。 序列化操作步骤接下来详细讲讲利用DataContractJsonSerializer 类将 C#对象序列化为JSON字符串的具体流程。 第一步,我们需要先创建好要进行序列化的对象。比如还是以刚才定义的Student 类为例,我们可以这样创建一个Student 类的实例:
第二步,实例化DataContractJsonSerializer 序列化器,这里要传入我们想要序列化的对象类型,代码如下:
第三步,创建一个MemoryStream 内存流对象,用于后续将序列化之后的 JSON格式数据写入到这个流当中,像这样:
第四步,利用刚才实例化好的序列化器的WriteObject 方法,把我们创建的对象写入到内存流中,对应代码为:
第五步,要从内存流中读取数据,在读取之前需要先将内存流的位置设置为 0,也就是起始位置,然后创建StreamReader 读取流中的数据,并将读取到的内容转换为字符串,代码示例如下:
最后,我们就可以得到序列化后的 JSON字符串了。完整的代码整合起来就是这样:
假如上述代码中Student 类对象的各个属性值分别是ID = 01,Name = "钉钉",Sex = "男",Age = 1,那最终序列化得到的 JSON字符串结果可能类似这样:{"ID":1,"Name":"钉钉","Age":1,"Sex":"男"}(实际结果会根据具体类结构和属性值情况有所不同哦),这样就完成了从 C#对象到JSON字符串的序列化操作啦。 反序列化操作步骤下面讲解将 JSON字符串反序列化为C#对象的具体操作步骤。 首先,我们得有一个 JSON字符串,这个字符串可以是从外部获取到的数据,比如从网络接口返回的JSON格式的数据内容等,假设我们现在已经有了这样一个JSON字符串变量toDes,示例如下:
第一步,要实例化DataContractJsonSerializer 反序列化器,同样需要传入要反序列化的目标对象类型,代码如下:
第二步,利用反序列化器的ReadObject 方法,从内存流中读取数据并还原成对应的 C#对象,像这样:
整合起来完整的反序列化代码示例如下:
当执行完上述反序列化操作后,如果反序列化成功,我们就可以得到一个还原后的Student 类对象,并且可以通过访问对象的属性来获取相应的值,例如像代码中那样输出ID、Name、Age、Sex 等属性的值,以此来验证反序列化的结果是否符合预期哦,这样就完成了从 JSON字符串到C#对象的反序列化过程啦。 四、借助 System.Text.Json进行对象映射
类的准备特点在使用System.Text.Json 进行对象映射相关操作时,其类的准备与之前介绍的一些方式有所不同。它并不依赖像System.Runtime.Serialization.Json 中那样特定的属性标记(如[DataContract] 和[DataMember] 等)来决定哪些属性参与序列化和反序列化。 System.Text.Json 主要依据公共属性和字段的可见性来进行序列化。只要类中的属性是公共的(使用public 修饰符),在默认情况下就会被包含在序列化和反序列化的过程中。例如,我们定义如下一个简单的Employee 类:
在上述代码中,Name、Age 和Department 这几个公共属性,在使用System.Text.Json 进行序列化时,都会自动被处理,不需要额外添加特殊的标记。这使得在一些简单的场景下,类的准备工作更加简洁直观,减少了代码中额外的属性标记负担。不过,如果想要对序列化和反序列化的过程进行更精细的控制,比如忽略某些属性或者改变属性序列化后的名称等,就需要借助System.Text.Json 提供的相关配置选项和特性来实现啦,后续我们会详细讲到哦。 序列化操作流程下面来详细说说利用System.Text.Json 进行对象序列化的具体操作流程哈。 首先,我们要创建好需要序列化的对象,就像前面定义的Employee 类,我们可以这样实例化一个对象:
接着,配置序列化相关的选项,这一步是通过JsonSerializerOptions 类来完成的。这个类提供了很多可配置的属性,例如: •WriteIndented 属性:如果将其设置为true,那么序列化后的 JSON字符串会进行格式化,有缩进和换行,方便阅读查看;若设置为false(默认值),则序列化后的 JSON字符串是紧凑的,没有多余的空格和换行哦。示例代码如下:
•PropertyNamingPolicy 属性:可以用来指定属性名称在序列化后的命名规则,比如设置为JsonNamingPolicy.CamelCase,那么原本在 C#类中采用帕斯卡命名法(首字母大写)的属性名,在序列化后的JSON字符串中就会变成驼峰命名法(首字母小写)形式啦。像这样:
配置好选项后,就可以执行序列化操作了,调用JsonSerializer.Serialize 方法,将对象和配置选项(如果有配置的话)作为参数传入,示例代码如下:
假设我们前面创建的Employee 对象属性值分别是Name = "小李",Age = 28,Department = "研发部",并且配置了WriteIndented = true 和PropertyNamingPolicy = JsonNamingPolicy.CamelCase,那最终序列化得到的 JSON字符串结果可能类似这样:
这样就完成了利用System.Text.Json 把 C#对象序列化为JSON字符串的操作啦,整个过程还是比较清晰明了的哦。 反序列化操作流程接下来讲讲如何通过System.Text.Json 将 JSON字符串反序列化为C#对象呀。 第一步,我们得先有一个 JSON字符串,这个字符串可能是从外部接口获取到的,或者是从文件中读取出来的数据等等,比如下面这样一个示例JSON字符串:
在 C#代码中可以这样定义这个字符串变量:
然后,同样需要配置反序列化相关的选项,也是通过JsonSerializerOptions 类来进行配置哦,配置的方法和序列化时类似,例如设置属性名称大小写不敏感等情况(如果有需要的话),像这样:
接着,就可以调用JsonSerializer.Deserialize 方法来执行反序列化操作啦,需要指定要反序列化的目标对象类型,示例代码如下:
如果反序列化成功,我们就可以通过访问deserializedEmp 对象的各个属性来获取相应的值啦,比如输出对象的属性值看看:
这样,就完成了从 JSON字符串到C#对象的反序列化过程哦,通过System.Text.Json 进行序列化和反序列化操作,在很多项目中都能方便地实现数据的转换和处理呢。 五、使用 Newtonsoft.Json(Json.NET)完成对象映射程序包引用与命名空间导入在 C#项目中若要使用Newtonsoft.Json(Json.NET)库来进行 JSON序列化/反序列化操作,首先需要引用相应的程序包并导入对应的命名空间哦。 引用程序包的常见方式是通过 NuGet程序包管理器,不同的开发工具操作略有不同。例如在Visual Studio中,可以点击“工具- NuGet包管理器-程序包管理器控制台”,然后在控制台输入命令“Install-Package Newtonsoft.Json”(不同版本可能命令稍有差异,比如有的版本后面会跟具体版本号等),回车后NuGet就会自动下载并安装Newtonsoft.Json程序包到项目中啦,像这样就引用成功了哦。 在成功引用程序包后,我们还需要在代码文件中导入对应的命名空间,这样才能使用该库提供的各种类和方法呀,导入的语句是“using Newtonsoft.Json;”,将这条语句添加到代码文件的顶部(通常在其他using语句一起的位置哦),就可以开始使用Newtonsoft.Json相关功能进行对象映射的操作啦,下面咱们接着看看具体的序列化和反序列化示例吧。 序列化示例与特性运用接下来看看如何利用 Newtonsoft.Json中的JsonConvert.SerializeObject方法将C#对象序列化为JSON字符串哈。 咱们先定义一个简单的类,比如下面这个表示学生信息的类:
然后创建这个类的对象,并调用 JsonConvert.SerializeObject方法进行序列化操作,示例代码如下:
上述代码运行后,输出结果会是这样的 JSON字符串格式:
在实际应用中,有时候我们可能不希望某些字段参与对象的 JSON序列化,这时候就可以使用[JsonIgnore]特性啦。例如,我们不想让“Sex”字段被序列化,那可以修改“Student”类的定义如下:
再执行同样的序列化操作,输出结果就会变成这样:
可以看到“Sex”字段就没有出现在序列化后的JSON字符串中了哦。 还有一种情况,我们可能想在对象序列化时更换字段的输出名称,比如简化字段名称以缩短 JSON字符串的长度等,这时就可以使用[JsonProperty]特性标识字段啦。假设我们想把“Description”字段在序列化后的名称改为“Desc”,代码可以这样写:
重新执行序列化操作后,输出结果如下:
通过这些特性的运用,我们可以更灵活地控制对象序列化后的 JSON字符串格式呢,方便满足不同的业务需求哦。 反序列化示例与注意事项下面咱们讲讲如何将 JSON字符串通过JsonConvert.DeserializeObject方法反序列化为C#对象哈。 先来看个简单的例子,假设我们有如下的 JSON字符串:
我们要把它反序列化为“Student”类的对象列表,对应的“Student”类定义如下(这里注意不要使用之前讲序列化特性时那些特殊的特性标记哦,保持常规的类定义就行):
在 C#代码中进行反序列化的操作示例如下:
上述代码执行后,就能成功将 JSON字符串反序列化为“Student”类的对象列表,并且可以通过遍历输出每个对象的属性值来验证反序列化的结果哦,输出结果会是这样:
这里有个需要注意的事项哈,在进行反序列化时,类中属性名称要和 JSON字符串中的键相对应哦。如果属性名称不一致,那可能会导致反序列化出来的对象属性值不正确或者出现异常情况呢。比如JSON字符串里某个键是“student_name”,而对应的C#类里属性定义是“StudentName”,那就没办法正确赋值啦,所以在编写代码和设计数据结构时,要保证这种对应关系哦,这样才能顺利地完成基于Newtonsoft.Json的对象反序列化操作呀,大家可以自己动手多试试不同的示例,加深理解哦。 六、不同方法的对比与选择建议各方法性能、功能对比在 C#开发中,常用的JSON序列化/反序列化方法有System.Runtime.Serialization.Json、System.Text.Json、Newtonsoft.Json等,它们在性能表现以及支持的功能特性方面存在一定差异。 •System.Runtime.Serialization.Json:这是.NET Framework内置的库,优势在于无需额外的引用,并且支持DataContract属性和WCF协定,比较适合在一些老项目中使用。不过,其性能相对较差,像在处理大量数据的序列化和反序列化时,效率可能不如其他几种方式。而且它不支持一些高级功能,例如自定义转换器,在面对复杂的JSON数据场景时,灵活性欠佳。 •System.Text.Json:作为.NET Core的一部分,在创建跨平台应用程序时,不需要额外的依赖项,使用起来较为方便。性能方面进行了优化,通常比Newtonsoft.Json更快,利用了新的读写API,采用更高效的内部实现,有更好的性能和内存利用率。在处理简单的JSON数据时,其提供的简化API也更容易操作,但默认是强类型转换,比如实体类定义的是字符串,JSON字符串返回的是整型,转换时会报错。另外,虽然默认强类型转换,但也可以通过自定义转换器等方式来实现弱类型转换,以满足更多不同的需求。 •Newtonsoft.Json(JSON.NET):它是一个成熟且使用广泛的第三方库,在.NET社区中被广泛接受和使用。拥有丰富的功能和强大的灵活性,比如支持完全自定义的序列化和反序列化逻辑,能处理循环引用、自定义转换器、忽略属性等等,可以方便地应对各种复杂的JSON数据场景。不过,它相对有较大的依赖包,并且在某些场景下,性能可能会低于一些最新的库。 根据项目场景选择合适方法在实际的项目开发中,选择哪种 JSON序列化/反序列化方法来实现对象映射,需要综合考虑多个因素,以下是一些依据不同项目情况给出的选择建议: •基于.NET版本: ◦如果是老项目,本身基于.NET Framework,且对性能要求不是特别极致,功能需求也相对常规,那么System.Runtime.Serialization.Json是可以胜任的,毕竟无需额外引用,能方便地集成到已有项目中,符合项目原本的技术栈特点。 ◦若是基于.NET Core开发的新项目,特别是创建跨平台应用程序时,System.Text.Json就比较合适了,它与.NET Core集成紧密,还自带性能优势以及简化的API,方便快捷地处理常见的JSON数据操作,减少额外依赖带来的潜在问题。 ◦而无论项目基于哪种.NET版本,只要涉及到较为复杂的JSON数据处理场景,比如需要处理循环引用、要对序列化和反序列化逻辑做深度定制、或者要灵活地处理各种数据类型转换等情况,Newtonsoft.Json就是一个很好的选择,虽然可能依赖包稍大些,但丰富的功能可以应对各种复杂需求。 •对性能和灵活性的需求: ◦当项目对性能有较高要求,例如是大数据量处理的应用,像电商平台的订单数据处理、大数据系统中的数据交互等场景,优先考虑 System.Text.Json,它在处理大量数据的序列化和反序列化时效率表现突出,能够保障系统整体的数据处理速度,避免性能瓶颈。 ◦如果项目更注重灵活性,比如需要频繁根据不同业务场景去动态调整对象序列化和反序列化的规则,像根据不同客户端需求输出不同格式的 JSON数据、要忽略某些属性或者改变属性序列化后的名称等情况,Newtonsoft.Json的优势就体现出来了,借助其丰富的功能特性,可以轻松实现各种自定义逻辑,满足多变的业务需求。 ◦要是项目只是处理一些简单常规的 JSON数据交互,性能要求也不是特别高,追求简洁方便的开发体验,System.Text.Json同样可以满足,利用它默认的配置和简单的API就能快速实现对象映射,减少开发成本和出错概率。 七、总结内容回顾在本文中,我们详细介绍了利用 JSON序列化/反序列化实现C#对象映射的几种主要方法,下面来简单回顾一下关键内容,帮助大家强化记忆哦。 首先是利用System.Runtime.Serialization.Json 实现对象映射,使用这个命名空间时,参与操作的类要标记[DataContract],类中的属性需标记[DataMember],这是进行序列化和反序列化的基础准备。序列化时,要先创建对象、实例化DataContractJsonSerializer 序列化器、创建MemoryStream 内存流对象,接着用序列化器的WriteObject 方法将对象写入内存流,最后从内存流中读取数据并转换为字符串,就得到了序列化后的 JSON字符串。反序列化与之类似,先有JSON字符串,实例化反序列化器后,用ReadObject 方法从内存流中读取数据还原成 C#对象。 System.Text.Json 进行对象映射时,类准备工作主要依据公共属性和字段的可见性,公共属性默认会被包含在序列化和反序列化过程中。序列化要先创建对象,通过JsonSerializerOptions 类配置相关选项,比如设置WriteIndented 属性控制字符串格式、PropertyNamingPolicy 属性指定属性名称的命名规则等,然后调用JsonSerializer.Serialize 方法执行序列化。反序列化则是先有 JSON字符串,同样配置好JsonSerializerOptions 类(按需配置属性名大小写不敏感等情况),再调用JsonSerializer.Deserialize 方法还原 C#对象。 使用Newtonsoft.Json(Json.NET) 库时,得先通过 NuGet程序包管理器引用程序包,并在代码文件中导入using Newtonsoft.Json; 命名空间。序列化可以通过JsonConvert.SerializeObject 方法实现,还能运用特性,像[JsonIgnore] 可让字段不参与序列化,[JsonProperty] 能更换字段的输出名称,使序列化更灵活。反序列化用JsonConvert.DeserializeObject 方法,不过要注意类中属性名称要和 JSON字符串中的键对应,不然可能出现赋值异常情况哦。 不同的方法各有特点,在性能、功能以及适用场景等方面都存在差异,大家可以根据实际项目情况去选择合适的方式来进行 C#对象映射呀。 拓展与展望随着技术的不断发展,JSON序列化/反序列化在C#对象映射中的应用也有着广阔的拓展空间呢。 从拓展应用方向来看,在微服务架构日益流行的当下,各个微服务之间的数据交互频繁,利用 JSON序列化/反序列化实现对象映射可以更好地保障数据格式的统一和交互的顺畅。例如,在一个电商系统的微服务架构里,商品服务、订单服务、用户服务等不同的微服务之间传递数据时,通过高效准确的对象映射,能让数据快速在各个环节流转,提升整个系统的协同效率。 而且,在跨平台开发越来越普遍的趋势下,像.NET Core支持的跨平台应用开发场景中,System.Text.Json 这类无需额外依赖项且性能优良的方式,有望在更多类型的项目里发挥重要作用,进一步优化数据传输和存储的效率。 对于想要进一步学习提升的朋友们来说,可以深入研究各个库的高级特性和自定义功能哦。比如深入了解Newtonsoft.Json 的自定义转换器实现原理,尝试自己编写复杂数据结构的转换逻辑,应对各种特殊的业务数据需求;或者探索System.Text.Json 如何更好地结合.NET Core的其他新特性,来打造高性能、低资源占用的应用程序。 此外,多参考开源项目里对于 JSON序列化/反序列化对象映射的优秀实践案例也是个不错的学习途径,从中汲取经验,运用到自己的实际项目中。 该文章在 2024/12/19 17:56:04 编辑过 |
关键字查询
相关文章
正在查询... |