swagger gin 文档接口排序,写了一个小工具,自定义接口排序

起因没找到swagger 自定义接口排序

代码原理就是替换 swag init 生成的docs.go paths 部分 ,取到swagger.json paths 部分排序,正则匹配docs.go paths 部分,然后通过自定义排序,替换paths部分,这个根据自定义的需求来

代码如下

go 复制代码
package main

import (
	"encoding/json"
	"fmt"
	"github.com/tidwall/gjson"
	orderedmap "github.com/wk8/go-ordered-map/v2"
	"log"
	"os"
	"regexp"
	"sort"
	"strconv"
	"strings"
)

// GOOS=darwin GOARCH=arm64 go build -x -v -ldflags "-s -w" -o swagger_sort main.go
type Endpoint struct {
	Post struct {
		Security    []map[string][]interface{} `json:"security"`
		Description string                     `json:"description"`
		Consumes    []string                   `json:"consumes"`
		Produces    []string                   `json:"produces"`
		Tags        []string                   `json:"tags"`
		Summary     string                     `json:"summary"`
		Parameters  []map[string]interface{}   `json:"parameters"`
		Responses   map[string]interface{}     `json:"responses"`
	} `json:"post"`
}

func main() {
	goPath := os.Args[1]
	swaggerPath := os.Args[2]
	if goPath == "" || swaggerPath == "" {
		log.Fatal("文件不存在")
		return
	}

	// 从doc.go中读取内容
	content, err := os.ReadFile(goPath)
	if err != nil {
		log.Fatalf("Error reading docs.go: %v", err)
	}

	newPathsContent := getNewContents(swaggerPath)
	// 正则匹配 "paths" 及其后面的 {} 内容,但保留 "definitions"
	r := regexp.MustCompile(`(?s)"paths": (\{.*?\}),\s*"definitions"`)
	matches := r.FindStringSubmatch(string(content))
	if matches == nil {
		fmt.Println("No match found!")
		return
	}
	//fmt.Println("Matched:", matches[1])


	// Replace matched content in docs.go with newPathsContent
	updatedContent := string(content)
	updatedContent = strings.Replace(updatedContent, matches[1], newPathsContent, 1)

	// Write the updated content back to docs.go
	err = os.WriteFile(goPath, []byte(updatedContent), 0644)
	if err != nil {
		log.Fatalf("Error writing to docs.go: %v", err)
	}

	fmt.Println("Successfully wrote to test.js and updated docs.go!")
}

func extractNumberFromSummary(summary string) int {
	parts := strings.Split(summary, ".")
	if len(parts) > 0 {
		num, err := strconv.Atoi(parts[0])
		if err == nil {
			return num
		}
	}
	return 0
}

func getNewContents(swaggerPath string) string {
	content, err := os.ReadFile(swaggerPath)

	if err != nil {
		log.Fatalf("Error reading swagger.json: %v", err)
	}
	str := gjson.Get(string(content), "paths").String()

	var data map[string]Endpoint
	if err := json.Unmarshal([]byte(str), &data); err != nil {
		panic(err)
	}

	type PathItem struct {
		Path string
		Ep   Endpoint
	}

	var paths []PathItem
	for k, v := range data {
		paths = append(paths, PathItem{k, v})
	}

	sort.Slice(paths, func(i, j int) bool {
		if len(paths[i].Ep.Post.Tags) > 0 {
			if paths[i].Ep.Post.Tags[0] == paths[j].Ep.Post.Tags[0] {
				numI := extractNumberFromSummary(paths[i].Ep.Post.Summary)
				numJ := extractNumberFromSummary(paths[j].Ep.Post.Summary)
				return numI < numJ
			} else if strings.Contains(paths[i].Ep.Post.Tags[0], "测试") {
				return false
			} else {
				return true
			}
		}
		return true

	})

	//bytePath, _ := json.MarshalIndent(paths, "", "    ")
	//fmt.Println(string(bytePath))

	// 创建一个新的 ordered map
	orderedData := orderedmap.New[string, Endpoint]()

	// 从排序后的切片中填充 ordered map
	for _, item := range paths {
		orderedData.Set(item.Path, item.Ep)
	}

	// 编码 ordered map
	sortedJSON, err := json.MarshalIndent(orderedData, "", "    ")
	if err != nil {
		panic(err)
	}

	fmt.Println(string(sortedJSON))
	return string(sortedJSON)
}

我的排序效果

相关推荐
呆萌很1 天前
【Gin】文件上传下载(单文件 + 多文件)
gin
先跑起来再说3 天前
Go 排行榜系统的工程化实现:分布式锁、快照表与定时刷新
分布式·go·gin
必胜刻5 天前
一个异步生成游戏功能的落地复盘:Redis Stream + WebSocket + 状态补偿
redis·websocket·golang·gin·状态补偿
TE-茶叶蛋6 天前
B-tree vs GIN Trigram vs HNSW
gin
曾几何时`8 天前
Go(一)Gin框架 和 GORM机制
开发语言·golang·gin
老毛肚9 天前
Gin + GORM 接口可视化测试
gin
lolo大魔王9 天前
Gin 框架中间件超详细实战教程(原理、全局中间件、路由中间件、自定义中间件、跨域、日志拦截)
中间件·gin
lolo大魔王9 天前
Gin 框架响应格式与 HTML 模板渲染完整实战教程
前端·html·gin
必胜刻18 天前
Go 调用Coze工作流实现 AI 游戏生成
开发语言·ai·golang·gin
比特森林探险记20 天前
context 在 gRPC / Gin / K8s 中的实战
容器·kubernetes·gin