使用 System.Text.Json 时,如何处理 Dictionary 中 Key 为自定义类型的问题
在使用 System.Text.Json 进行 JSON 序列化和反序列化操作时,我们会遇到一个问题:如何处理字典中的 Key 为自定义类型的问题。
背景说明
例如,我们有如下代码:
// 定义一个自定义类型
public class CustomType
{
public int Id { get; set; } public string Name { get; set; } // 获取字符串表示的 Key
public string Key => $"{Id}_{Name}";
} // 定义一个 Dictionary<CustomType, string> 类型的对象
Dictionary<CustomType, string> dictionary = new Dictionary<CustomType, string>
{
{ new CustomType { Id = 1, Name = "one" }, "one" },
{ new CustomType { Id = 2, Name = "two" }, "two" }
}; // 序列化字典
string json = JsonSerializer.Serialize(dictionary); // 反序列化字典
Dictionary<CustomType, string> dictionary2 = JsonSerializer.Deserialize<Dictionary<CustomType, string>>(json);
在上述代码中,我们定义了一个自定义类型 CustomType,并使用这个类型作为 Dictionary 的 Key 类型。
接下来,我们使用 JsonSerializer.Serialize 方法将字典序列化为 JSON 字符串,并使用 JsonSerializer.Deserialize 方法将 JSON 字符串反序列化为字典。
但是,在上述代码中,我们会发现,序列化字典时,字典中的 Key 会被序列化为一个 JSON 对象,而不是我们想要的字符串。
同样的,在反序列化 JSON 字符串时,JSON 对象中的 Key 会被反序列化为一个 CustomType 类型的对象,而不是我们想要的字符串。
这时,我们就需要使用一个自定义的 JSON 转换器来解决这个问题。
代码示例
首先,我们定义一个继承自 JsonConverter 的类型 CustomTypeConverter,该类型实现了 Read、Write、ReadAsPropertyName、WriteAsPropertyName 方法:
public class CustomTypeConverter : JsonConverter<CustomType>
{
public override CustomType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
// Deserialize object
return JsonSerializer.Deserialize<CustomType>(ref reader, options);
} public override void Write(Utf8JsonWriter writer, CustomType value, JsonSerializerOptions options)
{
// Serialize object
JsonSerializer.Serialize(writer, value, options);
} public override CustomType ReadAsPropertyName(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
// Read key as string
var stringValue = reader.GetString(); // Parse string to CustomType
return ParseCustomType(stringValue);
} public override void WriteAsPropertyName(Utf8JsonWriter writer, CustomType value, JsonSerializerOptions options)
{
// Write key as string
writer.WritePropertyName(value.Key);
} private CustomType ParseCustomType(string value)
{
// Parse string to CustomType
var parts = value.Split("_");
var id = int.Parse(parts[0]);
var name = parts[1]; return new CustomType
{
Id = id,
Name = name
};
}
}
在上述代码中,我们将 CustomType 类型的 Key 属性作为字典的 Key,在序列化操作中,将 Key 属性序列化为字符串,并在反序列化操作中,将字符串反序列化为 Key 属性。
接下来,我们使用这个自定义的 JSON 转换器来序列化和反序列化字典:
// 定义一个自定义类型
public class CustomType
{
public int Id { get; set; } public string Name { get; set; } // 获取字符串表示的 Key
public string Key => $"{Id}_{Name}";
} // 定义一个 Dictionary<CustomType, string> 类型的对象
Dictionary<CustomType, string> dictionary = new Dictionary<CustomType, string>
{
{ new CustomType { Id = 1, Name = "one" }, "one" },
{ new CustomType { Id = 2, Name = "two" }, "two" }
}; // 创建 JsonSerializerOptions 对象
var options = new JsonSerializerOptions(); // 添加自定义的 JSON 转换器
options.
Converters.Add(new CustomTypeConverter()); // 序列化字典
string jsonString = JsonSerializer.Serialize(dictionary, options); // 反序列化 JSON 字符串
var result = JsonSerializer.Deserialize<Dictionary<CustomType, string>>(jsonString, options);
在上述代码中,我们将 CustomType 类型的 Key 属性作为字典的 Key,在序列化操作中,将 Key 属性序列化为字符串,并在反序列化操作中,将字符串反序列化为 Key 属性。
使用建议
在使用 System.Text.Json 进行序列化和反序列化操作时,如果要处理字典中 Key 为自定义类型的问题,可以通过定义一个自定义的 JSON 转换器来解决。
在定义自定义的 JSON 转换器时,需要注意以下几点:
- 类型需要继承自 JsonConverter 类型。
- 类型需要实现 Read、Write、ReadAsPropertyName、WriteAsPropertyName 方法。
- 在 Read 方法中,需要将 JSON 字符串反序列化为 T 类型。
- 在 Write 方法中,需要将 T 类型序列化为 JSON 字符串。
- 在 ReadAsPropertyName 方法中,需要将 JSON 字符串反序列化为字典的 Key 属性。
- 在 WriteAsPropertyName 方法中,需要将字典的 Key 属性序列化为 JSON 字符串。
总结
本文通过一个实例,介绍了如何使用 System.Text.Json 进行序列化和反序列化操作时,处理字典中 Key 为自定义类型的问题。
在定义自定义的 JSON 转换器时,需要注意类型需要继承自 JsonConverter 类型,并实现 Read、Write、ReadAsPropertyName、WriteAsPropertyName 方法。
参考资料
本文采用 Chat OpenAI 辅助注水浇筑而成,如有雷同,完全有可能。
- 本文作者: newbe36524
- 本文链接: https://www.newbe.pro/ChatAI/How-serialize-custom-type-as-dictionary-key-in-system-text-json /
- 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
使用 System.Text.Json 时,如何处理 Dictionary 中 Key 为自定义类型的问题的更多相关文章
- 【译】System.Text.Json 的下一步是什么
.NET 5.0 最近发布了,并带来了许多新特性和性能改进.System.Text.Json 也不例外.我们改进了性能和可靠性,并使熟悉 Newtonsoft.Json 的人更容易采用它.在这篇文章中 ...
- .NET 5的System.Text.Json的JsonDocument类讲解
本文内容来自我写的开源电子书<WoW C#>,现在正在编写中,可以去WOW-Csharp/学习路径总结.md at master · sogeisetsu/WOW-Csharp (gith ...
- 在.Net Core 3.0中尝试新的System.Text.Json API
.NET Core 3.0提供了一个名为System.Text.Json的全新命名空间,它支持reader/writer,文档对象模型(DOM)和序列化程序.在此博客文章中,我将介绍它如何工作以及如何 ...
- .net core中关于System.Text.Json的使用
在.Net Framework的时候序列化经常使用Newtonsoft.Json插件来使用,而在.Net Core中自带了System.Text.Json,号称性能更好,今天抽空就来捣鼓一下. 使用起 ...
- [.Net Core 3.0+/.Net 5] System.Text.Json中时间格式化
简介 .Net Core 3.0开始全新推出了一个名为System.Text.Json的Json解析库,用于序列化和反序列化Json,此库的设计是为了取代Json.Net(Newtonsoft.Jso ...
- 使用.Net6中的System.Text.Json遇到几个常见问题及解决方案
前言 以前.NetCore是不内置JSON库的,所以大家都用Newtonsoft的JSON库,而且也确实挺好用的,不过既然官方出了标准库,那更方便更值得我们多用用,至少不用每次都nuget安装Newt ...
- c# System.Text.Json 精讲
本文内容来自我写的开源电子书<WoW C#>,现在正在编写中,可以去WOW-Csharp/学习路径总结.md at master · sogeisetsu/WOW-Csharp (gith ...
- [译]试用新的System.Text.Json API
译注 可能有的小伙伴已经知道了,在.NET Core 3.0中微软加入了对JSON的内置支持. 一直以来.NET开发者们已经习惯使用Json.NET这个强大的库来处理JSON. 那么.NET为什么要增 ...
- .NET Core 内置的 System.Text.Json 使用注意
System.Text.Json 是 .NET Core 3.0 新引入的高性能 json 解析.序列化.反序列化类库,武功高强,但毕竟初入江湖,炉火还没纯青,使用时需要注意,以下是我们在实现使用中遇 ...
- .NET Core 3.0 System.Text.Json 和 Newtonsoft.Json 行为不一致问题及解决办法
行为不一致 .NET Core 3.0 新出了个内置的 JSON 库, 全名叫做尼古拉斯 System.Text.Json - 性能更高占用内存更少这都不是事... 对我来说, 很多或大或小的项目能少 ...
随机推荐
- 研发效能之技术治理&技术治理架构师
最近很多公司专门设置了一个职位叫「技术治理架构师」,主要负责公司技术治理相关事宜.这是个非常有意思的职位.技术治理的活,之前我们也是做的,只是没有提的这么明确,一般都是研发效能团队.PMO.架构团队. ...
- echarts 饼图中间添加图片
饼图添加图片只需要配置两部分 option = { graphic: { // 这个属性可以在饼图内部填充图片,文字等 elements: [{ type: 'image',//需要填充图片,配置im ...
- aardio + PowerShell 可视化快速开发独立 EXE 桌面程序
aardio 可以方便地调用 PowerShell ,PowerShell 中也可以自由调用 aardio 对象与函数.不用带上体积很大的System.Management.Automation.dl ...
- 关于aws-SecurityGroup-安全组策略的批量添加的方法记录
因一些服务的客户端网络地址段计划变更,会影响到aws上配置这这些网段安全组策略所绑定的资源 因此需要先整理包含了出那些服务的网络地址段的安全组 然后根据旧网段的策略信息,将新的地址段给添加上,待后续正 ...
- 洛谷P1640 SCOI2010 连续攻击游戏 (并查集/匹配)
本题介绍两种做法: 1 并查集 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=1000005; 4 int ...
- C++ 栈和典型迷宫问题
C++ 栈和迷宫问题 1. 前言 栈是一种受限的数据结构,要求在存储数据时遵循先进后出(Last In First Out)的原则.可以把栈看成只有一个口子的桶子,进和出都是走的这个口子(也称为栈顶) ...
- java:找不到符号
出现这种情况的原因之一:实体类的字段修改过.实体类中的变量名修改.然而其他地方调用的字段名还是修改之前的变量.
- vue传值
在vue 中组件间的传参是必不可少的,下面说下几种传参方式 1.父组件传值给子组件,首先父组件发送的形式是用bind(用缩写:)绑定值到子组件身上.然后子组件用属性props接收 2.子组件传值父组件 ...
- 【题解】CF374C Inna and Dima
题面传送门 解决思路 本题是找最长路的图上问题,所以先考虑如何建图. 首先把每一个字母转化为数字,然后对于每一个点枚举四个方向,如果有下一个字母,就向那个点建一条边,可以用 \(vector\) 存图 ...
- 详解Native Memory Tracking之追踪区域分析
摘要:本篇图文将介绍追踪区域的内存类型以及 NMT 无法追踪的内存. 本文分享自华为云社区<[技术剖析]17. Native Memory Tracking 详解(3)追踪区域分析(二)> ...