十倍程序员 | 使用 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由多个JsonElementJsonProperty组成

  • 一个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的类,拿到namesapceclassname和 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();

使用

  1. 在项目中安装 NuGet 包

dotnet add package MyIO.ParseJsonAsClass.SourceGenerator
  1. 在项目中添加一个 JSON 文件


  "code": 200,
  "msg": "ok",
  "obj":"a":1,"subObj":"a":1,
  "data": [
    "1","2"
  ],
  "array": [
    "a":1.0,
    "a":null
  ]
  1. 在项目中添加一个 C# 文件

using MyIO;
namespace ConsoleApp1

    [ParseJsonAsClass("sample.txt")]
    internal partial class Class1
     
    

sample.txt 是上一步中添加的 JSON 文件的名称。

  1. 编译项目

总结

相关源代码已上传到 GitHub: https://github.com/feiyun0112/MyIO.ParseJsonAsClass.SourceGenerator,点击“阅读原文”可直达,欢迎 Star。

添加微信号【MyIO666】,邀你加入技术交流群

以上是关于十倍程序员 | 使用 Source Generator 将 JSON 转换成 C# 类的主要内容,如果未能解决你的问题,请参考以下文章

云计算中寻找十倍个股

微软开源,AutoML性能提高十倍!

微软开源,AutoML性能提高十倍!

堪比Web SQL:开源项目让IDB速度原地提升数十倍

彻底掌握连接池技术,使系统速度提升数十倍​!

一个跨界程序员:不务正业的这几年,我如何让自己的收入翻了十倍(转)