feat: 增加文档数据初始化逻辑

This commit is contained in:
2026-01-06 23:25:14 +08:00
parent 5d86daadeb
commit 3ea5af0709
3 changed files with 172 additions and 116 deletions

View File

@@ -19,108 +19,130 @@ import (
"github.com/getkin/kin-openapi/openapi3"
)
// NewGenerate 生成文档实例
func NewGenerate() *Generate {
return &Generate{
doc: &openapi3.T{
Extensions: map[string]any{},
OpenAPI: "3.1.0",
Components: &openapi3.Components{
Extensions: map[string]any{},
Origin: &openapi3.Origin{
Key: &openapi3.Location{
Line: 0,
Column: 0,
},
Fields: make(map[string]openapi3.Location),
},
Schemas: map[string]*openapi3.SchemaRef{},
Parameters: map[string]*openapi3.ParameterRef{},
Headers: map[string]*openapi3.HeaderRef{},
RequestBodies: map[string]*openapi3.RequestBodyRef{},
Responses: map[string]*openapi3.ResponseRef{},
SecuritySchemes: map[string]*openapi3.SecuritySchemeRef{},
Examples: map[string]*openapi3.ExampleRef{},
Links: map[string]*openapi3.LinkRef{},
Callbacks: map[string]*openapi3.CallbackRef{},
},
Info: &openapi3.Info{
Extensions: map[string]any{},
Origin: &openapi3.Origin{
Key: &openapi3.Location{
Line: 0,
Column: 0,
},
Fields: make(map[string]openapi3.Location),
},
Title: "服务 API接口 文档",
Description: "服务 API接口 文档",
TermsOfService: "",
Contact: &openapi3.Contact{
Extensions: map[string]any{},
Origin: &openapi3.Origin{
Key: &openapi3.Location{
Line: 0,
Column: 0,
},
Fields: make(map[string]openapi3.Location),
},
Name: "developer",
URL: "",
Email: "developer@test.com",
},
License: &openapi3.License{
Extensions: map[string]any{},
Origin: &openapi3.Origin{
Key: &openapi3.Location{
Line: 0,
Column: 0,
},
Fields: make(map[string]openapi3.Location),
},
Name: consts.LicenseApache20,
URL: consts.LicenseUrlTable[consts.LicenseApache20],
},
Version: "0.0.1",
},
Paths: &openapi3.Paths{
Extensions: map[string]any{},
Origin: &openapi3.Origin{
Key: &openapi3.Location{
Line: 0,
Column: 0,
},
Fields: make(map[string]openapi3.Location),
},
},
Security: []openapi3.SecurityRequirement{},
Servers: []*openapi3.Server{
{
Extensions: nil,
Origin: nil,
URL: "http://127.0.0.1:8080/v1",
Description: "开发环境",
Variables: nil,
},
},
Tags: []*openapi3.Tag{},
/*ExternalDocs: &openapi3.ExternalDocs{
Extensions: map[string]any{},
Origin: nil,
Description: "",
URL: "",
},*/
},
var (
DocManager = &Generate{
docTable: make(map[string]*openapi3.T),
}
)
// NewOpenApiDoc 生成文档实例
func NewOpenApiDoc(optionFunc ...OptionFunc) *openapi3.T {
t := &openapi3.T{
Extensions: map[string]any{},
OpenAPI: "3.1.0",
Components: &openapi3.Components{
Extensions: map[string]any{},
Origin: &openapi3.Origin{
Key: &openapi3.Location{
Line: 0,
Column: 0,
},
Fields: make(map[string]openapi3.Location),
},
Schemas: map[string]*openapi3.SchemaRef{},
Parameters: map[string]*openapi3.ParameterRef{},
Headers: map[string]*openapi3.HeaderRef{},
RequestBodies: map[string]*openapi3.RequestBodyRef{},
Responses: map[string]*openapi3.ResponseRef{},
SecuritySchemes: map[string]*openapi3.SecuritySchemeRef{},
Examples: map[string]*openapi3.ExampleRef{},
Links: map[string]*openapi3.LinkRef{},
Callbacks: map[string]*openapi3.CallbackRef{},
},
Info: &openapi3.Info{
Extensions: map[string]any{},
Origin: &openapi3.Origin{
Key: &openapi3.Location{
Line: 0,
Column: 0,
},
Fields: make(map[string]openapi3.Location),
},
Title: "服务 API接口 文档",
Description: "服务 API接口 文档",
TermsOfService: "",
Contact: &openapi3.Contact{
Extensions: map[string]any{},
Origin: &openapi3.Origin{
Key: &openapi3.Location{
Line: 0,
Column: 0,
},
Fields: make(map[string]openapi3.Location),
},
Name: "developer",
URL: "",
Email: "developer@test.com",
},
License: &openapi3.License{
Extensions: map[string]any{},
Origin: &openapi3.Origin{
Key: &openapi3.Location{
Line: 0,
Column: 0,
},
Fields: make(map[string]openapi3.Location),
},
Name: consts.LicenseApache20,
URL: consts.LicenseUrlTable[consts.LicenseApache20],
},
Version: "0.0.1",
},
Paths: &openapi3.Paths{
Extensions: map[string]any{},
Origin: &openapi3.Origin{
Key: &openapi3.Location{
Line: 0,
Column: 0,
},
Fields: make(map[string]openapi3.Location),
},
},
Security: []openapi3.SecurityRequirement{},
Servers: []*openapi3.Server{
{
Extensions: nil,
Origin: nil,
URL: "http://127.0.0.1:8080",
Description: "开发环境",
Variables: nil,
},
},
Tags: []*openapi3.Tag{},
/*ExternalDocs: &openapi3.ExternalDocs{
Extensions: map[string]any{},
Origin: nil,
Description: "",
URL: "",
},*/
}
for _, item := range optionFunc {
item(t)
}
return t
}
// Generate 生成 OpenApi 标准规范的文档
type Generate struct {
doc *openapi3.T
docTable map[string]*openapi3.T
}
// DocData 获取一个文档数据
func (g *Generate) DocData(docFlag string) *openapi3.T {
return g.docTable[docFlag]
}
func (g *Generate) NewOpenApiDoc(docFlag string, docOption ...OptionFunc) *openapi3.T {
t := NewOpenApiDoc()
for _, item := range docOption {
item(t)
}
g.docTable[docFlag] = t
return t
}
// AddApiDoc 添加接口文档
func (g *Generate) AddApiDoc(apiMeta define.UriConfig, request any, response any) error {
func (g *Generate) AddApiDoc(docFlag string, apiMeta define.UriConfig, request any, response any) error {
var (
err error
requestType reflect.Type
@@ -144,7 +166,7 @@ func (g *Generate) AddApiDoc(apiMeta define.UriConfig, request any, response any
}
schemaData := GenerateOpenAPISchema(requestType)
apiOperate, isRead := g.initApiConfig(apiMeta)
apiOperate, isRead := g.initApiConfig(docFlag, apiMeta)
requestTypeStr := requestType.String()
if isRead {
for paramName, paramConfig := range schemaData.Value.Properties {
@@ -196,12 +218,12 @@ func (g *Generate) AddApiDoc(apiMeta define.UriConfig, request any, response any
}
// 初始化接口配置
if _, exist := g.doc.Components.Schemas[requestTypeStr]; !exist {
g.doc.Components.Schemas[requestTypeStr] = schemaData
if _, exist := g.docTable[docFlag].Components.Schemas[requestTypeStr]; !exist {
g.docTable[docFlag].Components.Schemas[requestTypeStr] = schemaData
}
responseTypeStr := responseType.String()
if _, exist := g.doc.Components.Schemas[responseTypeStr]; !exist {
g.doc.Components.Schemas[responseTypeStr] = GenerateOpenAPISchema(responseType)
if _, exist := g.docTable[docFlag].Components.Schemas[responseTypeStr]; !exist {
g.docTable[docFlag].Components.Schemas[responseTypeStr] = GenerateOpenAPISchema(responseType)
}
desc := "请求成功"
apiOperate.Responses.Set(fmt.Sprintf("%v", http.StatusOK), &openapi3.ResponseRef{
@@ -217,7 +239,7 @@ func (g *Generate) AddApiDoc(apiMeta define.UriConfig, request any, response any
consts.MimeTypeJson: {
Extensions: nil,
Origin: nil,
Schema: g.doc.Components.Schemas[responseTypeStr],
Schema: g.docTable[docFlag].Components.Schemas[responseTypeStr],
Example: nil,
Examples: nil,
Encoding: nil,
@@ -230,9 +252,9 @@ func (g *Generate) AddApiDoc(apiMeta define.UriConfig, request any, response any
}
// initApiConfig 初始化接口配置, 并返回 operation 以及 是否读请求
func (g *Generate) initApiConfig(apiMeta define.UriConfig) (*openapi3.Operation, bool) {
if nil == g.doc.Paths.Value(apiMeta.Path) {
g.doc.Paths.Set(apiMeta.Path, &openapi3.PathItem{
func (g *Generate) initApiConfig(docFlag string, apiMeta define.UriConfig) (*openapi3.Operation, bool) {
if nil == g.docTable[docFlag].Paths.Value(apiMeta.Path) {
g.docTable[docFlag].Paths.Set(apiMeta.Path, &openapi3.PathItem{
Extensions: nil,
Origin: nil,
Ref: "",
@@ -261,29 +283,29 @@ func (g *Generate) initApiConfig(apiMeta define.UriConfig) (*openapi3.Operation,
isRead := false
switch apiMeta.RequestMethod {
case http.MethodGet:
g.doc.Paths.Value(apiMeta.Path).Get = newOperate
g.docTable[docFlag].Paths.Value(apiMeta.Path).Get = newOperate
isRead = true
case http.MethodHead:
g.doc.Paths.Value(apiMeta.Path).Head = newOperate
g.docTable[docFlag].Paths.Value(apiMeta.Path).Head = newOperate
isRead = true
case http.MethodConnect:
g.doc.Paths.Value(apiMeta.Path).Connect = newOperate
g.docTable[docFlag].Paths.Value(apiMeta.Path).Connect = newOperate
isRead = true
case http.MethodOptions:
g.doc.Paths.Value(apiMeta.Path).Options = newOperate
g.docTable[docFlag].Paths.Value(apiMeta.Path).Options = newOperate
isRead = true
case http.MethodTrace:
g.doc.Paths.Value(apiMeta.Path).Trace = newOperate
g.docTable[docFlag].Paths.Value(apiMeta.Path).Trace = newOperate
isRead = true
// 读请求
case http.MethodPost:
g.doc.Paths.Value(apiMeta.Path).Post = newOperate
g.docTable[docFlag].Paths.Value(apiMeta.Path).Post = newOperate
case http.MethodPut:
g.doc.Paths.Value(apiMeta.Path).Put = newOperate
g.docTable[docFlag].Paths.Value(apiMeta.Path).Put = newOperate
case http.MethodPatch:
g.doc.Paths.Value(apiMeta.Path).Patch = newOperate
g.docTable[docFlag].Paths.Value(apiMeta.Path).Patch = newOperate
case http.MethodDelete:
g.doc.Paths.Value(apiMeta.Path).Delete = newOperate
g.docTable[docFlag].Paths.Value(apiMeta.Path).Delete = newOperate
// 写请求
}
return newOperate, isRead

View File

@@ -34,20 +34,21 @@ func TestGenerate_AddApiDoc(t *testing.T) {
UpdatedAt *time.Time `json:"updated_at,omitempty" description:"更新时间"`
Category *Category `json:"category,omitempty" description:"分类"`
}
instance := NewGenerate()
instance.AddApiDoc(define.UriConfig{
docFlag := "demo"
DocManager.NewOpenApiDoc(docFlag)
DocManager.AddApiDoc(docFlag, define.UriConfig{
Path: "/a/b/c",
RequestMethod: http.MethodGet,
TagList: []string{"test"},
Desc: "测试接口",
}, Category{}, Product{})
instance.AddApiDoc(define.UriConfig{
DocManager.AddApiDoc(docFlag, define.UriConfig{
Path: "/a/b/c",
RequestMethod: http.MethodPost,
TagList: []string{"test"},
Desc: "测试接口",
}, Category{}, Product{})
// 输出 JSON
data, _ := json.MarshalIndent(instance.doc, "", " ")
data, _ := json.MarshalIndent(DocManager.docTable[docFlag], "", " ")
fmt.Println(string(data))
}

33
openapi/option.go Normal file
View File

@@ -0,0 +1,33 @@
// Package openapi ...
//
// Description : openapi ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2026-01-06 22:48
package openapi
import "github.com/getkin/kin-openapi/openapi3"
// OptionFunc 设置文档选项
type OptionFunc func(t *openapi3.T)
// WithServers 设置文档服务器
func WithServers(serverList openapi3.Servers) OptionFunc {
return func(t *openapi3.T) {
if len(serverList) == 0 {
return
}
t.Servers = serverList
}
}
// WithInfo 文档基础信息
func WithInfo(info *openapi3.Info) OptionFunc {
return func(t *openapi3.T) {
if nil == info {
return
}
t.Info = info
}
}