十倍程序员 | 使用 Source Generator 将 JSON 转换成 C# 类
Posted dotNET跨平台
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了十倍程序员 | 使用 Source Generator 将 JSON 转换成 C# 类相关的知识,希望对你有一定的参考价值。
前言
有时候,我们需要将通过 WebAPI 接收 JSON 字符串转换成 C# 代码。Visual Studio 提供了一个功能菜单可以轻松实现:
执行完成后,它会将生成的代码放在打开的的代码窗口中。
但是,如果有多个 JSON 字符串需要转换,这个过程非常繁琐,而且容易出错。
本文将介绍如何使用 Source Generator 将 JSON 字符串转换成 C# 类。
实现原理
解析 JSON 字符串
首先,我们需要解析 JSON 字符串,分析它的结构,再对应到 C# 类。这里,我们使用 System.Text.Json 库。
通过JsonDocument.Parse
方法解析 JSON 字符串,它将返回一个JsonDocument
对象:
using var jsonDocument = JsonDocument.Parse(json);
下图很好的说明了JsonDocument
的结构:
一个
JsonDocument
由多个JsonElement
和JsonProperty
组成一个
JsonElement
包含多个JsonProperty
一个
JsonProperty
的值也是一个JsonElement
。
通过递归遍历,我们可以解析出 JSON 字符串的结构。
匹配 C# 类型
接下来,我们需要将解析出的 JSON 字符串结构,匹配成 C# 类型。这里,我们使用如下代码来存储类和属性信息:
public class ParsedType
//名称
public string Name get; private set;
//类型
public TypeEnum Type get; private set;
//针对 Array 的类型
public ParsedType InternalType get; private set;
//属性列表
public IList<PropertyInfo> Properties get; internal set;
//是否是顶级类,用于区分嵌套子类
public bool IsRoot get; internal set;
public class PropertyInfo
public string Name get; private set;
public string JsonName get; private set;
public ParsedType Type get; private set;
生成 C# 类代码
匹配出了 C# 类型,生成 C# 类代码就非常容易了。这里,我们使用如下代码:
WriteFileStart(sw,name_space,class_name);
foreach (var type in types)
WriteClass(sw, type);
WriteFileEnd(sw);
types
是上一步解析出的 ParsedType 集合。
Source Generator
现在,我们需要使用 Source Generator 将完整流程实现。首先,我们定义了一个 Attribute:
const string attributeText = @"using System;
namespace MyIO
[AttributeUsage(AttributeTargets.Class)]
public sealed class ParseJsonAsClassAttribute : Attribute
public ParseJsonAsClassAttribute(string fileName)
FileName = fileName;
public string FileName get; set;
";
context.AddSource("MyIO.ParseJsonAsClassAttribute.g", SourceText.From(attributeText, System.Text.Encoding.UTF8));
然后,我们遍历项目中所有声明了ParseJsonAsClassAttribute
的类,拿到namesapce
、classname
和 JSON 字符串,生成 C# 类代码,然后写到项目中:
foreach (var memberSyntax in memberSyntaxes)
if (memberSyntax is ClassDeclarationSyntax classDeclarationSyntax)
var name_space = GetNamespace(classDeclarationSyntax);
var class_name = classDeclarationSyntax.Identifier.ValueText;
string json = GetJson(classDeclarationSyntax);
if (json == null)
continue;
var sourceText = GenerateSource(name_space, class_name, json);
if (sourceText != null)
this.context.AddSource("MyIO.ParseJsonAsClass." + classDeclarationSyntax.Identifier.ValueText + ".g", sourceText);
this.context.CancellationToken.ThrowIfCancellationRequested();
使用
在项目中安装 NuGet 包
dotnet add package MyIO.ParseJsonAsClass.SourceGenerator
在项目中添加一个 JSON 文件
"code": 200,
"msg": "ok",
"obj":"a":1,"subObj":"a":1,
"data": [
"1","2"
],
"array": [
"a":1.0,
"a":null
]
在项目中添加一个 C# 文件
using MyIO;
namespace ConsoleApp1
[ParseJsonAsClass("sample.txt")]
internal partial class Class1
sample.txt
是上一步中添加的 JSON 文件的名称。
编译项目
总结
相关源代码已上传到 GitHub: https://github.com/feiyun0112/MyIO.ParseJsonAsClass.SourceGenerator,点击“阅读原文”可直达,欢迎 Star。
添加微信号【MyIO666】,邀你加入技术交流群
以上是关于十倍程序员 | 使用 Source Generator 将 JSON 转换成 C# 类的主要内容,如果未能解决你的问题,请参考以下文章