184 lines
5.4 KiB
Go
184 lines
5.4 KiB
Go
|
package swaggerset
|
|||
|
|
|||
|
import (
|
|||
|
"encoding/json"
|
|||
|
"fmt"
|
|||
|
"log"
|
|||
|
"reflect"
|
|||
|
"strings"
|
|||
|
|
|||
|
"github.com/getkin/kin-openapi/openapi3"
|
|||
|
dynamicstruct "github.com/ompluscator/dynamic-struct"
|
|||
|
)
|
|||
|
|
|||
|
type messages struct {
|
|||
|
Msgs []message
|
|||
|
}
|
|||
|
|
|||
|
func newMessages() *messages {
|
|||
|
return &messages{
|
|||
|
Msgs: make([]message, 0),
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
type message struct {
|
|||
|
Type string
|
|||
|
RequestParam interface{}
|
|||
|
RequestBody interface{}
|
|||
|
Response interface{}
|
|||
|
}
|
|||
|
|
|||
|
func Run4() {
|
|||
|
// Загружаем Swagger-документ
|
|||
|
loader := openapi3.NewLoader()
|
|||
|
doc, err := loader.LoadFromFile("swagger2.yaml")
|
|||
|
if err != nil {
|
|||
|
log.Fatalf("Ошибка загрузки Swagger-документа: %v", err)
|
|||
|
}
|
|||
|
|
|||
|
// Пример обработки путей
|
|||
|
for path, pathItem := range doc.Paths.Map() {
|
|||
|
fmt.Printf("Path: %s\n", path)
|
|||
|
|
|||
|
// Пример обработки методов
|
|||
|
if pathItem.Get != nil {
|
|||
|
handleOperation("GET", pathItem.Get)
|
|||
|
}
|
|||
|
if pathItem.Post != nil {
|
|||
|
handleOperation("POST", pathItem.Post)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Обработка операции (GET или POST)
|
|||
|
func handleOperation(method string, operation *openapi3.Operation) (reqParam, reqBody, rsp interface{}) {
|
|||
|
fmt.Printf(" Method: %s\n", method)
|
|||
|
|
|||
|
// Обработка параметров (GET)
|
|||
|
if len(operation.Parameters) > 0 {
|
|||
|
paramsStruct := dynamicstruct.NewStruct()
|
|||
|
for _, paramRef := range operation.Parameters {
|
|||
|
param := paramRef.Value
|
|||
|
fieldName := capitalize(param.Name)
|
|||
|
goType := getGoType(param.Schema)
|
|||
|
|
|||
|
// В зависимости от того, где параметр находится (header, query, path, etc.), добавляем соответствующий тег
|
|||
|
switch param.In {
|
|||
|
case "query":
|
|||
|
paramsStruct = paramsStruct.AddField(fieldName, goType, fmt.Sprintf(`json:"%s" query:"%s"`, param.Name, param.Name))
|
|||
|
case "header":
|
|||
|
paramsStruct = paramsStruct.AddField(fieldName, goType, fmt.Sprintf(`json:"%s" header:"%s"`, param.Name, param.Name))
|
|||
|
default:
|
|||
|
paramsStruct = paramsStruct.AddField(fieldName, goType, fmt.Sprintf(`json:"%s"`, param.Name))
|
|||
|
}
|
|||
|
}
|
|||
|
requestStruct := paramsStruct.Build().New()
|
|||
|
fmt.Printf(" Request (Parameters): %+v\n", requestStruct)
|
|||
|
buf, _ := json.Marshal(requestStruct)
|
|||
|
fmt.Printf(" Request (Parameters) JSON: %s\n", buf)
|
|||
|
reqParam = requestStruct
|
|||
|
}
|
|||
|
|
|||
|
// Обработка тела запроса (POST)
|
|||
|
if operation.RequestBody != nil {
|
|||
|
for _, content := range operation.RequestBody.Value.Content {
|
|||
|
bodyFields := buildDynamicStruct(content.Schema)
|
|||
|
bodyStruct := reflect.StructOf(bodyFields)
|
|||
|
bodyInstance := reflect.New(bodyStruct).Interface()
|
|||
|
fmt.Printf(" Request (Body): %+v\n", bodyInstance)
|
|||
|
buf, _ := json.Marshal(bodyInstance)
|
|||
|
fmt.Printf(" Request (Body) JSON: %s\n", buf)
|
|||
|
reqBody = bodyInstance
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Обработка ответов
|
|||
|
for status, response := range operation.Responses.Map() {
|
|||
|
fmt.Printf(" Response Code: %s\n", status)
|
|||
|
for _, content := range response.Value.Content {
|
|||
|
responseFields := buildDynamicStruct(content.Schema)
|
|||
|
responseStruct := reflect.StructOf(responseFields)
|
|||
|
responseInstance := reflect.New(responseStruct).Interface()
|
|||
|
fmt.Printf(" Response: %+v\n", responseInstance)
|
|||
|
buf, _ := json.Marshal(responseInstance)
|
|||
|
fmt.Printf(" Response JSON: %s\n", buf)
|
|||
|
rsp = responseInstance
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// Рекурсивное создание структуры из схемы с учетом $ref
|
|||
|
func buildDynamicStruct(schema *openapi3.SchemaRef) []reflect.StructField {
|
|||
|
var builder []reflect.StructField
|
|||
|
fmt.Println("ref: ", schema.Ref)
|
|||
|
|
|||
|
if len(schema.Value.Properties) == 0 {
|
|||
|
return builder
|
|||
|
}
|
|||
|
|
|||
|
for name, prop := range schema.Value.Properties {
|
|||
|
fieldName := capitalize(name)
|
|||
|
if prop.Ref != "" || prop.Value.Type.Is("object") {
|
|||
|
subBuilder := buildDynamicStruct(prop)
|
|||
|
|
|||
|
sfield := reflect.StructField{
|
|||
|
Name: fieldName,
|
|||
|
Type: reflect.StructOf(subBuilder),
|
|||
|
Tag: reflect.StructTag(fmt.Sprintf(`json:"%s"`, name)),
|
|||
|
}
|
|||
|
|
|||
|
builder = append(builder, sfield)
|
|||
|
} else {
|
|||
|
sfield := reflect.StructField{
|
|||
|
Name: fieldName,
|
|||
|
Type: reflect.TypeOf(getGoType(prop)),
|
|||
|
Tag: reflect.StructTag(fmt.Sprintf(`json:"%s"`, name)),
|
|||
|
}
|
|||
|
|
|||
|
builder = append(builder, sfield)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return builder
|
|||
|
}
|
|||
|
|
|||
|
// Преобразование типа OpenAPI в тип Go
|
|||
|
func getGoType(schema *openapi3.SchemaRef) interface{} {
|
|||
|
switch {
|
|||
|
case schema.Value.Type.Is("string"):
|
|||
|
return ""
|
|||
|
case schema.Value.Type.Is("integer"):
|
|||
|
return 0
|
|||
|
case schema.Value.Type.Is("boolean"):
|
|||
|
return false
|
|||
|
case schema.Value.Type.Is("array"):
|
|||
|
return []interface{}{}
|
|||
|
case schema.Value.Type.Is("object"):
|
|||
|
return buildDynamicStruct(schema)
|
|||
|
default:
|
|||
|
return nil
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func capitalize(fieldName string) string {
|
|||
|
// Заменяем точки на подчеркивания для унификации
|
|||
|
fieldName = strings.ReplaceAll(fieldName, ".", "_")
|
|||
|
|
|||
|
// Разделяем строку по подчеркиваниям
|
|||
|
parts := strings.Split(fieldName, "_")
|
|||
|
if len(parts) == 1 {
|
|||
|
return strings.ToUpper(fieldName[:1]) + fieldName[1:]
|
|||
|
}
|
|||
|
|
|||
|
// Обрабатываем каждый фрагмент
|
|||
|
for i := 0; i < len(parts); i++ {
|
|||
|
// Капитализируем первые буквы всех частей, кроме первой
|
|||
|
parts[i] = strings.Title(parts[i])
|
|||
|
}
|
|||
|
|
|||
|
// Собираем строку обратно, соединяя части без подчеркиваний
|
|||
|
return strings.Join(parts, "")
|
|||
|
}
|