惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园_首页
T
Threat Research - Cisco Blogs
GbyAI
GbyAI
Y
Y Combinator Blog
美团技术团队
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
博客园 - 【当耐特】
S
SegmentFault 最新的问题
IT之家
IT之家
Recent Announcements
Recent Announcements
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
阮一峰的网络日志
阮一峰的网络日志
T
The Blog of Author Tim Ferriss
Martin Fowler
Martin Fowler
Microsoft Azure Blog
Microsoft Azure Blog
V
Visual Studio Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
U
Unit 42
WordPress大学
WordPress大学
博客园 - Franky
L
LangChain Blog
人人都是产品经理
人人都是产品经理
小众软件
小众软件
博客园 - 叶小钗
罗磊的独立博客
酷 壳 – CoolShell
酷 壳 – CoolShell
大猫的无限游戏
大猫的无限游戏
云风的 BLOG
云风的 BLOG
Vercel News
Vercel News
雷峰网
雷峰网
腾讯CDC
Google DeepMind News
Google DeepMind News
博客园 - 三生石上(FineUI控件)
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Help Net Security
Help Net Security
C
Check Point Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
N
News and Events Feed by Topic
V2EX - 技术
V2EX - 技术
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Schneier on Security
Schneier on Security
博客园 - 聂微东
A
Arctic Wolf
H
Heimdal Security Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Recent Commits to openclaw:main
Recent Commits to openclaw:main
T
The Exploit Database - CXSecurity.com
C
Cyber Attacks, Cyber Crime and Cyber Security
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Google DeepMind News
Google DeepMind News

博客园 - 唐宋元明清2188

Electron 桌面客户端 ASAR 热更新:替换一个文件完成版本切换 .NET Win32设置只读未对齐,导致NTFS文件系统识别异常 SDD-skills执行遗漏问题 SDD基于规范编程-OpenSpec及SuperPowers .NET 磁盘BitLocker加密-技术选型 .NET Win32磁盘动态卷触发“函数不正确”问题排查 .NET SqlSugar多线程下SqlSugarClient 的线程安全陷阱 .NET 本地Db数据库-技术方案选型 .NET 磁盘Bitlocker加密-Powershell操作 .NET 磁盘管理-技术方案选型 .NET 记录Amazon上传S3异常问题 .NET 阻止Windows关机以及阻止失败的一些原因 网络虚拟存储 Iscsi实现方案 Windows 网络存储ISCSI介绍 Windows 本地虚拟磁盘Vhdx .NET 数据拷贝方案选择 .NET 窗口置于最顶层 如何做好软件架构师 .NET开发一些书箱推荐 Windows应用开发-常用工具 WPF 记录鼠标、触摸多设备混合输入场景问题 .NET Bios相关数据读写
.NET 记录多框架下的Json序列化属性标记问题
唐宋元明清2188 · 2025-05-26 · via 博客园 - 唐宋元明清2188

有小伙伴反馈,System.Text.Json使用的序列化问题,经了解是System.Text.Json不兼容System.Runtime.Serialization.DataMemenber属性标记

来个demo,

 1 var testMode = new TestMode();
 2 testMode.ID = "aaa";
 3 var serialize = JsonSerializer.Serialize(testMode);
 4 Debug.WriteLine(serialize);
 5 
 6 [DataContract]
 7 public class TestMode
 8 {
 9     [DataMember(Name = "id")]
10     public string ID { get; set; }
11 }

所以DataMember是不适用system.Text.Json的。

我们梳理下各序列化方案下如何正确的使用属性标记

DataContract及DataMemenber

System.Runtime.Serialization下,有数据契约序列化DataContractSerializer,可以用于XML序列化及WCF数据传输

而它的胞弟Json序列化DataContractJsonSerializer,是早期 的.NET Json序列化方案。因性能较弱,Framework下大家逐渐使用NewtonSoft.Json来替换。但简单的Json序列化,依然可以使用DataContractJsonSerializer

DataContractJsonSerializer使用的属性标记是DataContract、DataMember,DataContract用于标记类,DataMember标记序列化的属性:

1 var stopwatch = new Stopwatch();
2 stopwatch.Start();
3 var serializer = new DataContractJsonSerializer(typeof(TestMode));
4 using (var stream = new MemoryStream())
5 {
6     serializer.WriteObject(stream, testMode);
7     string json = Encoding.UTF8.GetString(stream.ToArray());
8     Console.WriteLine($"{json},{stopwatch.ElapsedMilliseconds}ms");
9 }

Newtonsoft.Json是兼容DataContract、DataMember的,所以使用Newtonsoft.Json.JsonConvert可以正常的进行对DataMember的属性进行序列化。:

1 stopwatch.Restart();
2 var serializeObject = JsonConvert.SerializeObject(testMode);
3 Console.WriteLine($"{serializeObject},{stopwatch.ElapsedMilliseconds}ms");

Newtonsoft.Json内部是通过默认配置JsonConvert.DefaultSettings,来兼容DataContract标记,

1 var settings = new JsonSerializerSettings
2 {
3     ContractResolver = new DefaultContractResolver
4     {
5         IgnoreSerializableAttribute = false // 启用 DataContract 支持
6     }
7 };

Newtonsoft.Json虽然对DataMember兼容,但DataContract标记需要注意下:类加DataContract标记后,则只支持有标记DataMember的属性序列化。

输出结果:

DataMember均序列化正常。另外可以发现,在.NET Framework及.NET版本下,首次序列化性能DataContractJsonSerializer比NewtonSoft.Json好很多

System.Text.Json被称作现代Json序列化,System.Text.Json 不识别 [DataMember],如果必须兼容可通过自定义 JsonConverter 间接支持,但复杂。。不推荐

补充下DataMember使用的其它相关标记:

[IgnoreDataMember] - 忽略字段

[DataMember]EmitDefaultValue、Order、IsRequired - 控制默认值、排序、是否必填

我个人挺喜欢用DataContract的,可以明确标记序列化类,与业务数据类隔离开来。

JsonPropertyName

JsonPropertyName是System.Text.Json.Serialization命名空间下的Attribute类,只适用于JsonSerializer序列化方案

微软官方推荐使用,性能比Newtonsoft.Json更好。性能对比可参考 .NET Json序列化方案选择 - 唐宋元明清2188 - 博客园

也补充相关属性标记:

[JsonIgnore] - 忽略属性

[JsonRequired] - 必填

[JsonInclude] - 强制包含如private的私有字段

JsonProperty

JsonProerty是Newtonsoft.Json第三方组件下的属性标记类,专属Newtonsoft.Json-JsonConvert序列化方案

补充相关属性标记

[JsonIgnore] - 忽略属性

[JsonRequired] - 必填

Newtonsoft.Json与System.Text.Json属性标记很相似,不要混用了。

多框架下的属性标记

如果你的组件添加了.NETFramework以及.NET多个框架版本,因考虑不同框架下的最佳Json序列化性能,那你的序列化属性类可能就需要处理不同的属性标记了

同时给一个属性添加多个标记能解决问题:

1     [JsonProperty("id")]
2     [JsonPropertyName("id")]
3     [DataMember(Name = "id",)]
4     public string ID { get; set; }

但不建议,容易造成后续维护的风险,可能不小心就遗漏了一个。

最佳方案是,通过明确的框架类型来区分不同代码

引用组件:

1 #if NETFRAMEWORK
2 using Newtonsoft.Json;
3 #elif NET8_0
4 using System.Text.Json.Serialization;
5 #endif

添加序列化属性标记:

1 #if NETFRAMEWORK
2     [JsonProperty("id")]
3 #elif NET8_0
4     [JsonPropertyName("id")]
5 #endif

一个框架下,建议明确并统一使用一个序列化方案。性能对比可参考 .NET Json序列化方案选择 - 唐宋元明清2188 - 博客园