我目前正在寻找从大型OpenAPI规范中提取所有JSON模式的方法.我一直在使用以下NuGet软件包:

Microsoft.OpenApi v1.3.1 Microsoft.OpenApi.Readers v1.3.1

我希望用这些来解析一个大型开放API规范,并提取所有JSON模式,我可以将其解析为"Microsoft".OpenApi.模型.OpenApiSchema的对象.但我似乎无法从这些对象创建JSON模式并将其写入文件.

目前,我有以下几点:

using (FileStream fs = File.Open(file.FullName, FileMode.Open))
{
    var openApiDocument = new OpenApiStreamReader().Read(fs, out var diagnostic);
    foreach (var schema in openApiDocument.Components.Schemas)
    {
        var schemaName = schema.Key;
        var schemaContent = schema.Value;

        var outputDir = Path.Combine(outputDirectory.FullName, fileNameWithoutExtension);
        if (!Directory.Exists(outputDir))
        {
            Directory.CreateDirectory(outputDir);
        }
        var outputPath = Path.Combine(outputDir, schemaName + "-Schema.json");
        var outputString = schemaContent.Serialize(OpenApiSpecVersion.OpenApi3_0, OpenApiFormat.Json);
        using (TextWriter sw = new StreamWriter(outputPath, true))
        {
            sw.Write(outputString);
            sw.Close();
        }
    }
}

schemaContent似乎具有模式的所有相关属性,但我似乎无法确定将其从该对象转换为JSON模式的下一步.我肯定我错过了一些简单的东西,因此任何洞察都将不胜感激.

UPDATED

我有一点 idea ,并采用了稍微不同的方法,使用NewtonSoft Json.

var OpenApitext = File.ReadAllText(file.FullName, Encoding.UTF8);
var settings = new JsonSerializerSettings
{
    PreserveReferencesHandling = PreserveReferencesHandling.Objects,
    MetadataPropertyHandling = MetadataPropertyHandling.Ignore, //ign
    Formatting = Newtonsoft.Json.Formatting.Indented
};

dynamic openApiJson = JsonConvert.DeserializeObject<ExpandoObject>(OpenApitext, settings);

if (openApiJson?.components?.schemas != null)
{
    foreach (var schema in openApiJson.components.schemas)
    {
        var schemaString = JsonConvert.SerializeObject(schema, settings);

        var outputDir = Path.Combine(outputDirectory.FullName, fileNameWithoutExtension);
        if (!Directory.Exists(outputDir))
        {
            Directory.CreateDirectory(outputDir);
        }
        var outputPath = Path.Combine(outputDir, schema.Name + "-Schema.json");

        using (TextWriter sw = new StreamWriter(outputPath, true))
        {
            sw.Write(schemaString);
            sw.Close();
        }
    }
}

现在,这将允许我创建JSON模式并将其写入文件,但它不想解析引用.查看API规范,所有引用似乎都是API规范的本地引用.在循环模式并将其写入文件之前,我需要做什么来解析开放API规范中的所有引用?我做了一些研究,有几个人似乎自己构建了这个功能,但他们总是使用类对象作为支持它的方式,这是我在这里做不到的.

推荐答案

我通过microsoft/OpenAPI进行了联系.NET GitHub回购协议.由于一点巧合/巧合,我在那里和这里都得到了同一个人的回复.所以,谢谢你,达雷尔,你帮我解决了上面这个让我感到困惑的问题.我知道最后是因为我没有完全正确地实施它.

作为参考,下面的用例是采用一个相当大的OpenAPI规范(Json)并提取所引用的Json模式,同时确保在将其写入文件时解决Json指针($ref,$id)等问题.

我之所以想采用这种方法,是因为由于我必须使用的OpenAPI规范的大小,使用诸如Postman之类的预构建工具来提取模式非常困难.

我的实现的最后一段代码,有几行有点粗糙,我会在周末整理一下.

Console.WriteLine($"Processing file: {file.FullName}");
var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file.FullName);
var fileExtension = Path.GetExtension(file.FullName);

var reader = new OpenApiStreamReader();
var result = await reader.ReadAsync(new FileStream(file.FullName, FileMode.Open));

foreach (var schemaEntry in result.OpenApiDocument.Components.Schemas)
{
    var schemaFileName = schemaEntry.Key + ".json";
    Console.WriteLine("Creating " + schemaFileName);

    var outputDir = Path.Combine(outputDirectory.FullName, fileNameWithoutExtension);
    if (!Directory.Exists(outputDir))
    {
        Directory.CreateDirectory(outputDir);
    }
    var outputPath = Path.Combine(outputDir, schemaFileName + "-Schema.json");

    using FileStream? fileStream = new FileStream(outputPath, FileMode.CreateNew);
    var writerSettings = new OpenApiWriterSettings() { InlineLocalReferences = true, InlineExternalReferences = true };
    using var writer = new StreamWriter(fileStream);
    schemaEntry.Value.SerializeAsV2WithoutReference(new OpenApiJsonWriter(writer, writerSettings));
}

Csharp相关问答推荐

为什么我的弹丸朝错误的方向移动?

[0-n]范围内有多少个Integer在其小数表示中至少包含一个9?

如何使用PDFSharp将文本添加到现有PDF

禁用AutoSuggestBox项目更改时的动画?

O(N)测试失败

在. net毛伊岛窗口的深度链接已经创建""

在具有主构造函数的类中初始化属性时出现警告

如何在C#中从正则表达式中匹配一些数字但排除一些常量(也是数字)

无法通过绑定禁用条目

在ASP.NET Core Web API项目中通过中间件修改`Request.Path`不会更改使用的控制器/操作

如何使用NumberFormatInfo

如何将此方法参数化并使其更灵活?

交替的奇数

在Docker容器中运行API项目时,无法本地浏览到index.html

从Base64转换为不同的字符串返回相同的结果

如何使用.NET Aspire从Blazor应用程序与GRPC API通信?

在平行内使用跨度.用于循环

SignalR跨域

C#-如何将int引用获取到byte[]

除非首先访问使用的终结点,否则本地API上的终结点不起作用