Created
May 6, 2026 02:02
-
-
Save jacobslusser/19d4dfadf09b7c51ea706b9de167bd16 to your computer and use it in GitHub Desktop.
Prints swagger URL routes (paths)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Prints all routes (paths) defined in a Swagger/OpenAPI JSON | |
| // file in an ordered, simple format: | |
| // GET /weatherforecast | |
| // POST /weatherforecast | |
| // GET /weatherforecast/{id:int} | |
| // etc. | |
| using System.Text.Json; | |
| using System.Text.Json.Nodes; | |
| if (args.Length == 0) | |
| { | |
| Console.WriteLine("Usage: dotnet simple_swagger_routes.cs -- <path-to-swagger.json>"); | |
| return; | |
| } | |
| string filePath = args[0]; | |
| if (!File.Exists(filePath)) | |
| { | |
| Console.Error.WriteLine($"Error: File not found: {filePath}"); | |
| return; | |
| } | |
| try | |
| { | |
| string json = await File.ReadAllTextAsync(filePath); | |
| JsonNode? root = JsonNode.Parse(json); | |
| if (root?["paths"] is not JsonObject paths) | |
| { | |
| Console.Error.WriteLine("Error: No 'paths' section found in Swagger JSON."); | |
| return; | |
| } | |
| List<Route> routes = new(); | |
| foreach (var pathKv in paths) | |
| { | |
| string template = pathKv.Key; // e.g. "/weatherforecast/{id}" | |
| JsonObject? operations = pathKv.Value as JsonObject; | |
| if (operations is null) | |
| { | |
| continue; | |
| } | |
| foreach (var opKv in operations) | |
| { | |
| string method = opKv.Key.ToUpperInvariant(); // get, post, put, delete, etc. | |
| if (method is "PARAMETERS" or "SUMMARY" or "DESCRIPTION") | |
| { | |
| continue; | |
| } | |
| // Try to enhance template with parameter types (best effort) | |
| string enhancedTemplate = EnhanceTemplateWithTypes(template, opKv.Value as JsonObject); | |
| routes.Add(new Route(method, enhancedTemplate)); | |
| } | |
| } | |
| routes.Sort((a, b) => string.Compare(a.Template, b.Template, StringComparison.Ordinal)); | |
| foreach (var route in routes) | |
| { | |
| Console.WriteLine($"{route.Method,-7} {route.Template}"); | |
| } | |
| } | |
| catch (Exception ex) | |
| { | |
| Console.Error.WriteLine($"Error: {ex.Message}"); | |
| } | |
| static string EnhanceTemplateWithTypes(string template, JsonObject? operation) | |
| { | |
| if (operation?["parameters"] is not JsonArray parameters) | |
| { | |
| return template; | |
| } | |
| foreach (var param in parameters) | |
| { | |
| if (param?["in"]?.GetValue<string>() != "path") | |
| { | |
| continue; | |
| } | |
| string? name = param?["name"]?.GetValue<string>(); | |
| string? type = GetSchemaType(param?["schema"] as JsonObject); | |
| if (!string.IsNullOrEmpty(name)) | |
| { | |
| string placeholder = $"{{{name}}}"; | |
| string typed = string.IsNullOrEmpty(type) ? placeholder : $"{{{name}:{type}}}"; | |
| template = template.Replace(placeholder, typed); | |
| } | |
| } | |
| return template; | |
| } | |
| static string GetSchemaType(JsonObject? schema) | |
| { | |
| if (schema is null) | |
| { | |
| return string.Empty; | |
| } | |
| string? type = schema["type"]?.GetValue<string>(); | |
| string? format = schema["format"]?.GetValue<string>(); | |
| if (type == "integer") | |
| { | |
| return format == "int64" ? "long" : "int"; | |
| } | |
| if (type == "number") | |
| { | |
| return format == "double" ? "double" : "float"; | |
| } | |
| if (type == "boolean") | |
| { | |
| return "bool"; | |
| } | |
| if (type == "string") | |
| { | |
| if (format == "date-time") | |
| { | |
| return "DateTime"; | |
| } | |
| if (format == "uuid") | |
| { | |
| return "Guid"; | |
| } | |
| return "string"; | |
| } | |
| return type ?? string.Empty; | |
| } | |
| sealed record Route(string Method, string Template); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment