From 42bbb1056e0e3e0394a6e168c4326d5643b9f924 Mon Sep 17 00:00:00 2001 From: Johan de Klerk <jdeklerk00@gmail.com> Date: Thu, 17 Mar 2022 14:16:49 +0200 Subject: [PATCH] docs: Schema types --- api_documentation/api_documentation.go | 90 +++++++++++++++----------- 1 file changed, 52 insertions(+), 38 deletions(-) diff --git a/api_documentation/api_documentation.go b/api_documentation/api_documentation.go index 25257fb..2bead15 100644 --- a/api_documentation/api_documentation.go +++ b/api_documentation/api_documentation.go @@ -25,9 +25,9 @@ type DocSchemas struct { type DocMethodInfo struct { Description string `json:"description"` Tags []string `json:"tags"` - RequestBody DocRequestBody `json:"requestBody"` + RequestBody *DocRequestBody `json:"requestBody,omitempty"` Parameters []DocParam `json:"parameters,omitempty"` - Responses map[string]DocResponseValue `json:"responses,omitempty"` + Responses *map[string]DocResponseValue `json:"responses,omitempty"` } type DocRequestBody struct { @@ -40,11 +40,11 @@ type DocRequestBody struct { type DocParam struct { Name string `json:"name"` In string `json:"in"` - Type string `json:"type"` Description string `json:"description"` - Schema DocSchema `json:"schema"` + Schema interface{} `json:"schema"` } + type DocSchema struct { Ref string `json:"$ref"` } @@ -92,11 +92,19 @@ func GetDocs(endpointHandlers map[string]map[string]interface{}) (Docs, error) { if name == "" { name = f.Name } + name = strings.Replace(name, ",omitempty", "", -1) + + schema, err := StructSchema(f.Type) + if err != nil { + return Docs{}, err + } + parameter := DocParam{ Name: name, - Type: fmt.Sprintf("%v", f.Type), + In: "query", Description: f.Tag.Get("doc"), + Schema: schema, } docMethod.Parameters = append(docMethod.Parameters, parameter) @@ -108,7 +116,7 @@ func GetDocs(endpointHandlers map[string]map[string]interface{}) (Docs, error) { bodyTypeString := getType(body) - docMethod.RequestBody = DocRequestBody{ + docMethod.RequestBody = &DocRequestBody{ Description: "Some description", Required: true, Content: map[string]interface{} { @@ -118,11 +126,13 @@ func GetDocs(endpointHandlers map[string]map[string]interface{}) (Docs, error) { }, } - schema, err := StructSchema(handler.RequestBodyType.Field(0).Type) - if err != nil { - return Docs{}, err + if handler.RequestBodyType.Kind() == reflect.Struct && handler.RequestBodyType.NumField() > 0 { + schema, err := StructSchema(handler.RequestBodyType.Field(0).Type) + if err != nil { + return Docs{}, err + } + docs.Components.Schemas[bodyTypeString] = schema } - docs.Components.Schemas[bodyTypeString] = schema } // Response @@ -140,29 +150,16 @@ func GetDocs(endpointHandlers map[string]map[string]interface{}) (Docs, error) { }, } - docMethod.Responses = responses + docMethod.Responses = &responses - schema, err := StructSchema(handler.ResponseType.Field(0).Type) - if err != nil { - return Docs{}, err + if handler.ResponseType.Kind() == reflect.Struct && handler.ResponseType.NumField() > 0 { + schema, err := StructSchema(handler.ResponseType.Field(0).Type) + if err != nil { + return Docs{}, err + } + docs.Components.Schemas[responseBodyTypeString] = schema } - docs.Components.Schemas[responseBodyTypeString] = schema } - - - - - - //describe request schema - // var err error - // docMethod.Request, err = DocSchema(fmt.Sprintf("%s %s %s", method, path, "request"), handler.RequestBodyType) - // if err != nil { - // return Docs{}, errors.Wrapf(err, "failed to document request") - // } - // docMethod.Response, err = DocSchema(fmt.Sprintf("%s %s %s", method, path, "response"), handler.ResponseType) - // if err != nil { - // return Docs{}, errors.Wrapf(err, "failed to document response") - // } } docPath[strings.ToLower(method)] = docMethod @@ -193,22 +190,36 @@ func StructSchema(t reflect.Type) (interface{}, error) { if t.Kind() == reflect.Ptr { - schema["optional"] = true + // schema["optional"] = true t = t.Elem() } switch t.Kind() { case reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8, reflect.Int, - reflect.Uint64, reflect.Uint32, reflect.Uint16, reflect.Uint8, reflect.Uint, - reflect.Float64, reflect.Float32, - reflect.Bool, - reflect.String: - schema["type"] = fmt.Sprintf("%v", t) + reflect.Uint64, reflect.Uint32, reflect.Uint16, reflect.Uint8, reflect.Uint: + schema["type"] = "integer" + schema["format"] = fmt.Sprintf("%v", t) + case reflect.Float64, reflect.Float32: + schema["type"] = "number" + schema["format"] = fmt.Sprintf("%v", t) + case reflect.Bool: + schema["type"] = "boolean" + schema["format"] = fmt.Sprintf("%v", t) + case reflect.String: + schema["type"] = "string" + schema["format"] = fmt.Sprintf("%v", t) case reflect.Interface: - schema["type"] = "interface{}" //any value...? + schema["type"] = "object" //any value...? case reflect.Struct: + + if t.String() == "time.Time" { + schema["type"] = "string" + schema["format"] = "date" + return schema, nil + } + schema["type"] = "object" properties := map[string]interface{}{} @@ -224,6 +235,8 @@ func StructSchema(t reflect.Type) (interface{}, error) { } fieldName = strings.Replace(fieldName, ",omitempty", "", -1) + + var err error fieldDesc := f.Tag.Get("doc") if fieldDesc == "" { @@ -238,7 +251,7 @@ func StructSchema(t reflect.Type) (interface{}, error) { schema["properties"] = properties case reflect.Map: - schema["type"] = "map" + schema["type"] = "object" // keySchema, err := DocSchema("key", t.Key()) // if err != nil { // return nil, errors.Wrapf(err, "cannot make schema for %v map key", t) @@ -252,6 +265,7 @@ func StructSchema(t reflect.Type) (interface{}, error) { case reflect.Slice: schema["type"] = "array" + schema["items"] = t.Elem() // elemSchema, err := DocSchema("items", t.Elem()) // if err != nil { // return nil, errors.Wrapf(err, "cannot make schema for %v slice elem", t) -- GitLab