C# 对象序列化之序列化为Json文件(一)
目录
1.概念
1.1原理
1.2用途
1.3 JSON序列化
1.4 二进制和XML序列化
2. 序列化为JSON
2.1 简单的序列化
2.2 复杂的序列化
3 忽略属性
3.1 忽略单个属性
3.2 忽略所有只读属性
3.3 忽略所有Null的属性
4 序列化为格式化的JSON
5 自定义属性名称和值
5.1 自定义单个属性名称
5.2 对所有 JSON 属性名称使用 camel 大小写
5.3 使用自定义 JSON 属性命名策略
5.4 序列化字典
5.5 作为字符串的枚举
5.6 不区分大小写的属性匹配
6 处理溢出 JSON
1.概念
序列化是指将对象转换成字节流,从而存储对象或将对象传输到内存、数据库或文件的过程。 它的主要用途是保存对象的状态,以便能够在需要时重新创建对象。 反向过程称为“反序列化”。
1.1原理
将对象序列化为带有数据的流。 该流还可能包含有关对象类型的信息,例如其版本、区域性和程序集名称。 可以将此流中的对象存储在数据库、文件或内存中。
1.2用途
通过序列化,开发人员可以保存对象的状态,并能在需要时重新创建对象,同时还能存储对象和交换数据。 通过序列化,开发人员可以执行如下操作:
- 使用 Web 服务将对象发送到远程应用程序
- 将对象从一个域传递到另一个域
- 将对象通过防火墙传递为 JSON 或 XML 字符串
- 跨应用程序维护安全或用户特定的信息
1.3 JSON序列化
System.Text.Json 命名空间包含用于 JavaScript 对象表示法 (JSON) 序列化和反序列化的类。 JSON 是一种常用于在 Web 上共享数据的开放标准。
JSON 序列化将对象的公共属性序列化为符合 RFC 8259 JSON 规范的字符串、字节数组或流。 若要控制 JsonSerializer 对类的实例进行序列化或反序列化的方法,请执行以下操作:
- 使用 JsonSerializerOptions 对象
- 将 System.Text.Json.Serialization 命名空间中的特性应用于类或属性
- 实现自定义转换器
1.4 二进制和XML序列化
System.Runtime.Serialization 命名空间包含用于对二进制和 XML 进行序列化和反序列化的类。
二进制序列化使用二进制编码来生成精简的序列化以供使用,如基于存储或套接字的网络流。 在二进制序列化中,所有成员(包括只读成员)都会被序列化,且性能也会有所提升。
警告:二进制序列化可能会十分危险。 有关详细信息,请参阅BinaryFormatter security guide。
XML 序列化将对象的公共字段和属性或方法的参数和返回值序列化成符合特定 XML 架构定义语言 (XSD) 文档要求的 XML 流。 XML 序列化生成已转换成 XML 的强类型类,其中包含公共属性和字段。 System.Xml.Serialization 包含用于对 XML 进行序列化和反序列化的类。 将特性应用于类和类成员,从而控制 XmlSerializer 如何序列化或反序列化类的实例。
2. 序列化为JSON
2.1 简单的序列化
假设有这样一个对象:
public class WeatherForecast{public DateTimeOffset Date { get; set; }public int TemperatureCelsius { get; set; }public string Summary { get; set; }}
你要将其实例序列化,并写入到Json文件:
static void Main(string[] args){WeatherForecast weatherForecast = new WeatherForecast{Date = DateTime.Now,TemperatureCelsius = 20,Summary = "it is a good day!"};string jsonString = JsonSerializer.Serialize(weatherForecast);// 异步序列化//using FileStream createStream = File.Create(fileName);//await JsonSerializer.SerializeAsync(createStream, weatherForecast);File.WriteAllText("weather.json", jsonString);
}
2.2 复杂的序列化
假设有这样一个更复杂的类:
public class WeatherForecastWithPOCOs{public DateTimeOffset Date { get; set; }public int TemperatureCelsius { get; set; }public string Summary { get; set; }public string SummaryField;public IList<DateTimeOffset> DatesAvailable { get; set; }public Dictionary<string, HighLowTemps> TemperatureRanges { get; set; }public string[] SummaryWords { get; set; }}public class HighLowTemps{public int High { get; set; }public int Low { get; set; }}
这次我们实行反序列化实验,假设再你的程序目录下已经有一个Json文件(我取名为:weatherPocos.json):
{"Date": "2019-08-01T00:00:00-07:00","TemperatureCelsius": 25,"Summary": "Hot","DatesAvailable": ["2019-08-01T00:00:00-07:00","2019-08-02T00:00:00-07:00"],"TemperatureRanges": {"Cold": {"High": 20,"Low": -10},"Hot": {"High": 60,"Low": 20}},"SummaryWords": ["Cool","Windy","Humid"]
}
将Json序列化为WeatherForecastWithPOCOs对象:
string jsonString2 = File.ReadAllText("weatherPocos.json");var weatherPoco = JsonSerializer.Deserialize<WeatherForecastWithPOCOs>(jsonString2);//异步操作//using FileStream openStream = File.OpenRead(fileName);//weatherForecast = await JsonSerializer.DeserializeAsync<WeatherForecast>(openStream);Console.WriteLine(weatherPoco.Date);
3 忽略属性
将 C# 对象序列化为 JavaScript 对象表示法 (JSON) 时,默认情况下,所有公共属性都会序列化。 如果不想让某些属性出现在生成的 JSON 中,则有几个选项可用。 本文将介绍如何根据各种条件忽略属性:
- 单个属性
- 所有只读属性
- 所有 null 值属性
3.1 忽略单个属性
若要忽略单个属性,请使用 [JsonIgnore] 特性。
下面是要进行序列化的示例类型和 JSON 输出:
public class WeatherForecastWithIgnoreAttribute
{public DateTimeOffset Date { get; set; }public int TemperatureCelsius { get; set; }[JsonIgnore]public string Summary { get; set; }
}
这样,当我们序列化上面的对象时,json文件如下:
{"Date": "2019-08-01T00:00:00-07:00","TemperatureCelsius": 25,
}
3.2 忽略所有只读属性
如果属性包含公共 getter 而不是公共 setter,则属性为只读。 若要在序列化时忽略所有只读属性,请将 JsonSerializerOptions.IgnoreReadOnlyProperties 设置为 true
,如以下示例中所示:
var options = new JsonSerializerOptions
{IgnoreReadOnlyProperties = true,WriteIndented = true
};
jsonString = JsonSerializer.Serialize(weatherForecast, options);
举个例子:
定义类如下:
public class WeatherForecastWithROProperty
{public DateTimeOffset Date { get; set; }public int TemperatureCelsius { get; set; }public string Summary { get; set; }public int WindSpeedReadOnly { get; private set; } = 35;
}
序列化的结果:
{"Date": "2019-08-01T00:00:00-07:00","TemperatureCelsius": 25,"Summary": "Hot",
}
此选项仅适用于序列化。 在反序列化过程中,默认情况下会忽略只读属性。
3.3 忽略所有Null的属性
若要在序列化时忽略所有 null 值属性,请将 IgnoreNullValues 属性设置为 true
,如以下示例中所示:
var options = new JsonSerializerOptions
{IgnoreNullValues = true,WriteIndented = true
};
jsonString = JsonSerializer.Serialize(weatherForecast, options);
倘若对象如下:
Property | 值 |
---|---|
Date
|
8/1/2019 12:00:00 AM -07:00
|
TemperatureCelsius
|
25
|
Summary
|
null
|
实际结果为:
{"Date": "2019-08-01T00:00:00-07:00","TemperatureCelsius": 25
}
4 序列化为格式化的JSON
默认情况下,序列化得到的JSON文件会被压缩,也就是我们上面看到的树形结构会压缩成一行,如下:
{"Date":"2019-08-01T00:00:00-07:00","TemperatureCelsius":25,"Summary":"Hot","DatesAvailable":["2019-08-01T00:00:00-07:00","2019-08-02T00:00:00-07:00"],"TemperatureRanges":{"Cold":{"High":20,"Low":-10},"Hot":{"High":60,"Low":20}},"SummaryWords":["Cool","Windy","Humid"]}
若要输出带格式的JSON,需要将 JsonSerializerOptions.WriteIndented 设置为 true
如果你通过相同的选项重复使用 JsonSerializerOptions
,则请勿在每次使用时都创建新的 JsonSerializerOptions
实例。对每个调用重复使用同一实例。 有关详细信息,请参阅重用 JsonSerializerOptions 实例。
5 自定义属性名称和值
默认情况下,序列化为Json的每个key名和你类中的会保持完全一致,但是你也可以进行修改,以达到自定义。
5.1 自定义单个属性名称
若要设置单个属性的名称,请使用 [JsonPropertyName] 特性。下面是要进行序列化的示例类型和生成的 JSON:
public class WeatherForecastWithPropertyNameAttribute
{public DateTimeOffset Date { get; set; }public int TemperatureCelsius { get; set; }public string Summary { get; set; }[JsonPropertyName("Wind")]public int WindSpeed { get; set; }
}
你会看到WindSpeed的key 变为Wind:
{"Date": "2019-08-01T00:00:00-07:00","TemperatureCelsius": 25,"Summary": "Hot","Wind": 35
}
此特性设置的属性名称:
- 同时适用于两个方向(序列化和反序列化)。
- 优先于属性命名策略。
5.2 对所有 JSON 属性名称使用 camel 大小写
若要对所有 JSON 属性名称使用 camel 大小写,请将 JsonSerializerOptions.PropertyNamingPolicy 设置为 JsonNamingPolicy.CamelCase
,如下面的示例中所示:
var serializeOptions = new JsonSerializerOptions
{PropertyNamingPolicy = JsonNamingPolicy.CamelCase,WriteIndented = true
};
jsonString = JsonSerializer.Serialize(weatherForecast, serializeOptions);
public class WeatherForecastWithPropertyNameAttribute
{public DateTimeOffset Date { get; set; }public int TemperatureCelsius { get; set; }public string Summary { get; set; }[JsonPropertyName("Wind")]public int WindSpeed { get; set; }
}
{"date": "2019-08-01T00:00:00-07:00","temperatureCelsius": 25,"summary": "Hot","Wind": 35
}
camel 大小写属性命名策略:
- 适用于序列化和反序列化。
- 由
[JsonPropertyName]
特性替代。 这便是示例中的 JSON 属性名称Wind
不是 camel 大小写的原因。
5.3 使用自定义 JSON 属性命名策略
若要使用自定义 JSON 属性命名策略,请创建派生自 JsonNamingPolicy 的类,并替代 ConvertName 方法,如下面的示例中所示:
using System.Text.Json;namespace SystemTextJsonSamples
{public class UpperCaseNamingPolicy : JsonNamingPolicy{public override string ConvertName(string name) =>name.ToUpper();}
}
然后,将 JsonSerializerOptions.PropertyNamingPolicy 属性设置为命名策略类的实例:
var options = new JsonSerializerOptions
{PropertyNamingPolicy = new UpperCaseNamingPolicy(),WriteIndented = true
};
jsonString = JsonSerializer.Serialize(weatherForecast, options);
下面是要进行序列化的示例类和 JSON 输出:
public class WeatherForecastWithPropertyNameAttribute
{public DateTimeOffset Date { get; set; }public int TemperatureCelsius { get; set; }public string Summary { get; set; }[JsonPropertyName("Wind")]public int WindSpeed { get; set; }
}
{"DATE": "2019-08-01T00:00:00-07:00","TEMPERATURECELSIUS": 25,"SUMMARY": "Hot","Wind": 35
}
JSON 属性命名策略:
- 适用于序列化和反序列化。
- 由
[JsonPropertyName]
特性替代。 这便是示例中的 JSON 属性名称Wind
不是大写的原因。
5.4 序列化字典
如果要序列化的对象的属性为 Dictionary<string,TValue>
类型,则 string
键可转换为 camel 大小写。 为此,请将 DictionaryKeyPolicy 设置为 JsonNamingPolicy.CamelCase
,如下面的示例中所示:
var options = new JsonSerializerOptions
{DictionaryKeyPolicy = JsonNamingPolicy.CamelCase,WriteIndented = true
};
jsonString = JsonSerializer.Serialize(weatherForecast, options);
使用名为 TemperatureRanges
且具有键值对 "ColdMinTemp", 20
和 "HotMinTemp", 40
的字典序列化对象会产生类似于以下示例的 JSON 输出:
{"Date": "2019-08-01T00:00:00-07:00","TemperatureCelsius": 25,"Summary": "Hot","TemperatureRanges": {"coldMinTemp": 20,"hotMinTemp": 40}
}
字典键的 camel 大小写命名策略仅适用于序列化。 如果对字典进行反序列化,即使为 DictionaryKeyPolicy
指定 JsonNamingPolicy.CamelCase
,键也会与 JSON 文件匹配
5.5 作为字符串的枚举
默认情况下,枚举会序列化为数字。 若要将枚举名称序列化为字符串,请使用 JsonStringEnumConverter。
例如,假设需要序列化以下具有枚举的类:
public class WeatherForecastWithEnum
{public DateTimeOffset Date { get; set; }public int TemperatureCelsius { get; set; }public Summary Summary { get; set; }
}public enum Summary
{Cold, Cool, Warm, Hot
}
如果 Summary 为 Hot
,则默认情况下序列化的 JSON 具有数值 3:
{"Date": "2019-08-01T00:00:00-07:00","TemperatureCelsius": 25,"Summary": 3
}
下面的示例代码序列化枚举名称(而不是数值),并将名称转换为 camel 大小写:
options = new JsonSerializerOptions
{WriteIndented = true,Converters ={new JsonStringEnumConverter(JsonNamingPolicy.CamelCase)}
};
jsonString = JsonSerializer.Serialize(weatherForecast, options);
生成的 JSON 类似于以下示例:
{"Date": "2019-08-01T00:00:00-07:00","TemperatureCelsius": 25,"Summary": "hot"
}
options = new JsonSerializerOptions
{Converters ={new JsonStringEnumConverter(JsonNamingPolicy.CamelCase)}
};
weatherForecast = JsonSerializer.Deserialize<WeatherForecastWithEnum>(jsonString, options);
5.6 不区分大小写的属性匹配
默认情况下,反序列化会查找 JSON 与目标对象属性之间区分大小写的属性名称匹配。 若要更改该行为,请将 JsonSerializerOptions.PropertyNameCaseInsensitive 设置为 true
:
var options = new JsonSerializerOptions
{PropertyNameCaseInsensitive = true
};
var weatherForecast = JsonSerializer.Deserialize<WeatherForecast>(jsonString, options);
下面是具有 camel 大小写属性名称的示例 JSON。 它可以反序列化为具有帕斯卡拼写法属性名称的以下类型。
{"date": "2019-08-01T00:00:00-07:00","temperatureCelsius": 25,"summary": "Hot",
}
public class WeatherForecast
{public DateTimeOffset Date { get; set; }public int TemperatureCelsius { get; set; }public string Summary { get; set; }
}
6 处理溢出 JSON
反序列化时,可能会在 JSON 中收到不是由目标类型的属性表示的数据。 例如,假设目标类型如下:
public class WeatherForecast
{public DateTimeOffset Date { get; set; }public int TemperatureCelsius { get; set; }public string Summary { get; set; }
}
要反序列化的 JSON 如下:
{"Date": "2019-08-01T00:00:00-07:00","temperatureCelsius": 25,"Summary": "Hot","DatesAvailable": ["2019-08-01T00:00:00-07:00","2019-08-02T00:00:00-07:00"],"SummaryWords": ["Cool","Windy","Humid"]
}
如果将显示的 JSON 反序列化为显示的类型,则 DatesAvailable
和 SummaryWords
属性无处可去,会丢失。 若要捕获额外数据(如这些属性),请将 [JsonExtensionData] 特性应用于类型 Dictionary<string,object>
或 Dictionary<string,JsonElement>
的属性:
public class WeatherForecastWithExtensionData
{public DateTimeOffset Date { get; set; }public int TemperatureCelsius { get; set; }public string Summary { get; set; }[JsonExtensionData]public Dictionary<string, object> ExtensionData { get; set; }
}
将前面显示的 JSON 反序列化为此示例类型时,额外数据会成为 ExtensionData
属性的键值。
Property | 值 | 说明 |
---|---|---|
Date
|
"8/1/2019 12:00:00 AM -07:00"
|
|
TemperatureCelsius
|
0
|
区分大小写的不匹配(JSON 中的 temperatureCelsius ),因此未设置属性。
|
Summary
|
"Hot"
|
|
ExtensionData
|
temperatureCelsius: 25
|
因为大小写不匹配,所以此 JSON 属性是额外属性,会成为字典中的键值对。 |
DatesAvailable
|
[ "8/1/2019 12:00:00 AM -07:00", "8/2/2019 12:00:00 AM -07:00" ]
|
JSON 中的额外属性会成为键值对,将数组作为值对象。 |
SummaryWords
|
[ "Cool", "Windy", "Humid" ]
|
JSON 中的额外属性会成为键值对,将数组作为值对象。 |
序列化目标对象时,扩展数据键值对会成为 JSON 属性,就如同它们处于传入 JSON 中一样:
{"Date": "2019-08-01T00:00:00-07:00","TemperatureCelsius": 0,"Summary": "Hot","temperatureCelsius": 25,"DatesAvailable": ["2019-08-01T00:00:00-07:00","2019-08-02T00:00:00-07:00"],"SummaryWords": ["Cool","Windy","Humid"]
}
请注意,ExtensionData
属性名称不会出现在 JSON 中。 此行为使 JSON 可以进行往返,而不会丢失任何不会以其他方式进行反序列化的额外数据。
C# 对象序列化之序列化为Json文件(一)相关推荐
- Jquery 将表单序列化为Json对象
大家知道Jquery中有serialize方法,可以将表单序列化为一个"&"连接的字符串,但却没有提供序列化为Json的方法.不过,我们可以写一个插件实现. 我在网上看到有 ...
- JavaScriptSerializer类 对象序列化为JSON,JSON反序列化为对象
JavaScriptSerializer 类由异步通信层内部使用,用于序列化和反序列化在浏览器和 Web 服务器之间传递的数据.说白了就是能够直接将一个C#对象传送到前台页面成为javascript对 ...
- php直接json_encnode对象,将PHP对象序列化为JSON
所以我在 php.net左右徘徊,了解有关将PHP对象序列化为JSON的信息,当我偶然发现新的 JsonSerializable Interface时.它只有PHP> = 5.4,我在5.3.x ...
- js对象序列化为json字符串
网上找了找将js对象序列化为json字符串的方法.结果都不近人意,最后自己写了一个. 注意你得自己为Date增加toString()方法. function Serialize(obj){switch ...
- python 数据库查询序列化_python-将sqlalchemy类序列化为json
我正在尝试将sqlalchemy查询的结果(列表)序列化为json. 这是课程: class Wikilink(Base): __tablename__='Wikilinks' __table_arg ...
- 将Roaring Bitmap序列化为JSON
近期在实现一个数据结构时使用到了位图索引(bitmap index)[1],本文就来粗浅聊聊位图(bitmap). 一. 什么是bitmap 位图索引使用位数组(bit array,也有叫bitset ...
- [置顶] AMF序列化为对象和AMF序列化为二进制字节流
在使用Flex作为页面前端驱动Socket通讯时,一般使用AMF格式来进行的发送和接收,因此就要涉及到不同的数据格式的转换. 下面提供了AMF序列化为对象和AMF序列化为二进制字节流的方法,代码如下: ...
- Newtonsoft.Json.dll序列化为json,null值自动过滤
Newtonsoft.Json.dll序列化为json,null值自动过滤 原文:Newtonsoft.Json.dll序列化为json,null值自动过滤 var jSetting = new Js ...
- 关于DateTime对象序列化为Json之后的若干问题
将Datetime对象序列化成Json对象是常有的事情,微软的序列化方法会将Datetime对象序列化成一个字符串: "\/Date(1234656000000)\/" 这样的字符 ...
最新文章
- android studio 混淆jar,android studio如何生成混淆代码的jar
- 从补码的来源剖析到为啥补码=原码按位取反+1
- 一个实际的例子学习 SAP BTP Java 应用的 @Before 注解使用方式
- python的循环语句机制_Python-for循环的内部机制
- Linux 线程占用CPU过高定位分析
- flowable 设置流程跟踪高亮线的颜色
- html文本最小长度,CSS中处理不同长度文本的几种小技巧
- java正则表达式 ascii_Java——正则表达式
- 【Python】五子棋项目记录
- 基于JAVA+Servlet+JSP+MYSQL的问卷调查管理系统
- 利用Servlet做一套增删改查
- Unity中Debug打印信息的颜色设置
- SEO黑帽寄生虫快排的生成原理及做法[详解]
- 正切函数半角定理推导
- 爱企查与天眼查也来啦~
- Unity实现键鼠控制立方体移动旋转
- html日志网页,以HTML为表现的日志记录组件
- HDU 6078 Wavel Sequence(dp)
- 实现极致节能,维谛技术(Vertiv)有哪些特殊技能?
- 50种编程语言打印hello world