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, "") }