#2 - change to micro-proto/openapi
This commit is contained in:
@@ -5,8 +5,8 @@ import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/getkin/kin-openapi/openapi3"
|
||||
dynamicstruct "github.com/ompluscator/dynamic-struct"
|
||||
openapi "go.unistack.org/micro-proto/v4/openapiv3"
|
||||
)
|
||||
|
||||
type Message struct {
|
||||
@@ -20,17 +20,16 @@ type httpRequest struct {
|
||||
Body interface{}
|
||||
}
|
||||
|
||||
func handleOperation(method string, operation *openapi3.Operation) (reqParam, reqBody, rsp interface{}) {
|
||||
fmt.Printf(" Method: %s\n", method)
|
||||
|
||||
func handleOperation(operation *openapi.Operation, doc *openapi.Document) (reqParam, reqBody, rsp interface{}) {
|
||||
// Обработка параметров (GET)
|
||||
if len(operation.Parameters) > 0 {
|
||||
paramsStruct := dynamicstruct.NewStruct()
|
||||
for _, paramRef := range operation.Parameters {
|
||||
param := paramRef.Value
|
||||
var param *openapi.Parameter
|
||||
param = paramRef.GetParameter()
|
||||
fieldName := capitalize(param.Name)
|
||||
jsonName := strings.ToLower(param.Name[:1]) + param.Name[1:]
|
||||
goType := getGoType(param.Schema)
|
||||
goType := getGoType(doc, param.Schema)
|
||||
|
||||
// В зависимости от того, где параметр находится (header, query, path, etc.), добавляем соответствующий тег
|
||||
switch param.In {
|
||||
@@ -47,9 +46,17 @@ func handleOperation(method string, operation *openapi3.Operation) (reqParam, re
|
||||
}
|
||||
|
||||
// Обработка тела запроса (POST)
|
||||
if operation.RequestBody != nil {
|
||||
for _, content := range operation.RequestBody.Value.Content {
|
||||
bodyFields := buildDynamicStruct(content.Schema)
|
||||
if operation.GetRequestBody() != nil {
|
||||
if operation.GetRequestBody().GetRequestBody() != nil {
|
||||
bodyFields := buildDynamicStruct(doc, operation.GetRequestBody().GetRequestBody().GetContent().GetAdditionalProperties()[0].GetValue().GetSchema())
|
||||
bodyStruct := reflect.StructOf(bodyFields)
|
||||
bodyInstance := reflect.New(bodyStruct).Interface()
|
||||
// Получили тело запроса
|
||||
reqBody = bodyInstance
|
||||
}
|
||||
if operation.GetRequestBody().GetReference() != nil {
|
||||
schemOrRef := findReference(doc, operation.GetRequestBody().GetReference().GetXRef())
|
||||
bodyFields := buildDynamicStruct(doc, schemOrRef)
|
||||
bodyStruct := reflect.StructOf(bodyFields)
|
||||
bodyInstance := reflect.New(bodyStruct).Interface()
|
||||
// Получили тело запроса
|
||||
@@ -58,10 +65,19 @@ func handleOperation(method string, operation *openapi3.Operation) (reqParam, re
|
||||
}
|
||||
|
||||
// Обработка ответов
|
||||
for status, response := range operation.Responses.Map() {
|
||||
fmt.Printf(" Response Code: %s\n", status)
|
||||
for _, content := range response.Value.Content {
|
||||
responseFields := buildDynamicStruct(content.Schema)
|
||||
for _, rspOrRef := range operation.Responses.ResponseOrReference {
|
||||
if rspOrRef.GetValue().GetResponse() != nil {
|
||||
for _, prop := range rspOrRef.Value.GetResponse().GetContent().GetAdditionalProperties() {
|
||||
responseFields := buildDynamicStruct(doc, prop.GetValue().GetSchema())
|
||||
responseStruct := reflect.StructOf(responseFields)
|
||||
responseInstance := reflect.New(responseStruct).Interface()
|
||||
// Получили структуру ответа
|
||||
rsp = responseInstance
|
||||
}
|
||||
}
|
||||
if rspOrRef.GetValue().GetReference() != nil {
|
||||
schemaOrRef := findReference(doc, rspOrRef.GetValue().GetReference().GetXRef())
|
||||
responseFields := buildDynamicStruct(doc, schemaOrRef)
|
||||
responseStruct := reflect.StructOf(responseFields)
|
||||
responseInstance := reflect.New(responseStruct).Interface()
|
||||
// Получили структуру ответа
|
||||
@@ -73,30 +89,42 @@ func handleOperation(method string, operation *openapi3.Operation) (reqParam, re
|
||||
}
|
||||
|
||||
// Рекурсивное создание структуры из схемы с учетом $ref
|
||||
func buildDynamicStruct(schema *openapi3.SchemaRef) []reflect.StructField {
|
||||
func buildDynamicStruct(doc *openapi.Document, schemaOrRef *openapi.SchemaOrReference) []reflect.StructField {
|
||||
var sfields []reflect.StructField
|
||||
|
||||
if len(schema.Value.Properties) == 0 {
|
||||
return sfields
|
||||
var schema *openapi.Schema
|
||||
if schemaOrRef.GetSchema() != nil {
|
||||
schema = schemaOrRef.GetSchema()
|
||||
}
|
||||
if schemaOrRef.GetReference() != nil {
|
||||
name := strings.Split(schemaOrRef.GetReference().GetXRef(), "#/components/schemas/")[1]
|
||||
fieldName := capitalize(name)
|
||||
subBuilder := buildDynamicStruct(doc, findReference(doc, schemaOrRef.GetReference().GetXRef()))
|
||||
sfield := reflect.StructField{
|
||||
Name: fieldName,
|
||||
Type: reflect.StructOf(subBuilder),
|
||||
Tag: reflect.StructTag(fmt.Sprintf(`json:"%s"`, name)),
|
||||
}
|
||||
sfields = append(sfields, sfield)
|
||||
}
|
||||
|
||||
for name, prop := range schema.Value.Properties {
|
||||
fieldName := capitalize(name)
|
||||
if prop.Ref != "" || prop.Value.Type.Is("object") {
|
||||
subBuilder := buildDynamicStruct(prop)
|
||||
for _, prop := range schema.GetProperties().GetAdditionalProperties() {
|
||||
fieldName := capitalize(prop.GetName())
|
||||
if prop.GetValue().GetReference() != nil {
|
||||
subBuilder := buildDynamicStruct(doc, prop.GetValue())
|
||||
|
||||
sfield := reflect.StructField{
|
||||
Name: fieldName,
|
||||
Type: reflect.StructOf(subBuilder),
|
||||
Tag: reflect.StructTag(fmt.Sprintf(`json:"%s"`, name)),
|
||||
Tag: reflect.StructTag(fmt.Sprintf(`json:"%s"`, prop.GetName())),
|
||||
}
|
||||
|
||||
sfields = append(sfields, sfield)
|
||||
} else {
|
||||
}
|
||||
if prop.GetValue().GetSchema() != nil {
|
||||
sfield := reflect.StructField{
|
||||
Name: fieldName,
|
||||
Type: reflect.TypeOf(getGoType(prop)),
|
||||
Tag: reflect.StructTag(fmt.Sprintf(`json:"%s"`, name)),
|
||||
Type: reflect.TypeOf(getGoType(doc, prop.GetValue())),
|
||||
Tag: reflect.StructTag(fmt.Sprintf(`json:"%s"`, prop.GetName())),
|
||||
}
|
||||
|
||||
sfields = append(sfields, sfield)
|
||||
@@ -106,25 +134,41 @@ func buildDynamicStruct(schema *openapi3.SchemaRef) []reflect.StructField {
|
||||
return sfields
|
||||
}
|
||||
|
||||
func findReference(doc *openapi.Document, ref string) *openapi.SchemaOrReference {
|
||||
var result *openapi.SchemaOrReference
|
||||
ref = strings.Split(ref, "#/components/schemas/")[1]
|
||||
|
||||
for _, prop := range doc.Components.Schemas.GetAdditionalProperties() {
|
||||
if prop.Name == ref {
|
||||
result = prop.Value
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// Преобразование типа OpenAPI в тип Go
|
||||
func getGoType(schema *openapi3.SchemaRef) interface{} {
|
||||
switch {
|
||||
case schema.Value.Type.Is("string"):
|
||||
func getGoType(doc *openapi.Document, schema *openapi.SchemaOrReference) interface{} {
|
||||
switch schema.GetSchema().Type {
|
||||
case "string":
|
||||
return ""
|
||||
case schema.Value.Type.Is("integer"):
|
||||
case "integer":
|
||||
return 0
|
||||
case schema.Value.Type.Is("boolean"):
|
||||
case "boolean":
|
||||
return false
|
||||
case schema.Value.Type.Is("array"):
|
||||
case "array":
|
||||
return []interface{}{}
|
||||
case schema.Value.Type.Is("object"):
|
||||
return buildDynamicStruct(schema)
|
||||
case "object":
|
||||
return buildDynamicStruct(doc, schema)
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func capitalize(fieldName string) string {
|
||||
if fieldName == "" {
|
||||
return fieldName
|
||||
}
|
||||
// Заменяем точки на подчеркивания для унификации
|
||||
fieldName = strings.ReplaceAll(fieldName, ".", "_")
|
||||
|
||||
|
Reference in New Issue
Block a user