C#使用JObject解析OpenAPI规范提取接口元数据实现方法
C# 扁平化处理OpenAPI文档提取接口信息实现方案
核心思路
基于Newtonsoft.Json的JObject.SelectTokens方法,通过JSONPath通配符语法遍历OpenAPI规范的层级结构,回溯父节点属性提取所需的四类字段,无需引入重型OpenAPI解析库即可实现需求。
问题修正
你初始代码中传入的"paths"查询条件仅会选中整个paths根对象,无法遍历到内部的接口路径、HTTP方法子节点,需要使用多层通配符匹配到最底层的操作节点。
完整实现代码
首先确保项目已引入Newtonsoft.Json包,若需处理YAML格式可额外引入YamlDotNet包做格式转换。
using Newtonsoft.Json.Linq; // 读取并解析OpenAPI文档(JSON格式直接读取,YAML格式可先通过YamlDotNet转为JObject) string openApiContent = File.ReadAllText("spec.json"); JObject spec = JObject.Parse(openApiContent); // JSONPath规则说明: // $.paths 定位到根节点下的paths集合 // 第一层.* 匹配paths下所有key对应的子节点(即每个接口路径节点) // 第二层.* 匹配路径节点下所有key对应的子节点(即每个HTTP方法对应的操作节点) IEnumerable<JToken> operationNodes = spec.SelectTokens("$.paths.*.*"); List<string> flatResult = new List<string>(); // 合法HTTP方法列表,用于过滤paths下的parameters、$ref等非操作节点 HashSet<string> validHttpMethods = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "get", "post", "put", "delete", "patch", "head", "options", "trace" }; foreach (JToken opNode in operationNodes) { // 从父节点路径提取HTTP方法名 string httpMethod = opNode.Parent?.Path.Split('.').Last()?.ToLower(); if (string.IsNullOrEmpty(httpMethod) || !validHttpMethods.Contains(httpMethod)) continue; // 提取核心字段 string summary = opNode.Value<string>("summary") ?? string.Empty; string tag = opNode.SelectToken("tags")?.First?.Value<string>() ?? string.Empty; // 向上回溯两层父节点,提取接口路径 string apiPath = opNode.Parent?.Parent?.Path.Split('.').Last()?.Trim('"') ?? string.Empty; // 按要求格式拼接结果 flatResult.Add($"\"{summary}\", \"{tag}\", \"{apiPath}\", \"{httpMethod}\""); } // 输出结果 flatResult.ForEach(Console.WriteLine);
运行效果
针对你提供的示例OpenAPI片段,代码运行后输出完全匹配预期:
"Get Entity", "Things", "/entities/{id}", "get" "Update Entity", "Things", "/entities/{id}", "put" "Get Other", "Others", "/otherEntities/{id}", "get" "Update Other", "Others", "/otherEntities/{id}", "put"
大文件处理注意事项
- 若处理百MB以上的超大型OpenAPI文档,不要直接使用
JObject.Parse全量加载到内存,可改用JsonTextReader做流式解析,逐节点识别操作节点,大幅降低内存占用 - YAML格式文档可通过YamlDotNet先将YAML反序列化为动态对象,再序列化为JSON字符串后复用上述逻辑,无需单独写YAML解析规则
- 部分规范会在操作节点上使用
$ref引用公共定义,遇到这类场景可在提取字段前先判断$ref属性,加载对应引用节点的内容再提取字段
内容的提问来源于stack exchange,提问作者Andrew Roberts
相关产品推荐
相关产品推荐

