github.com/gogf/gf/v2@v2.7.4/net/goai/goai_shema_ref.go (about) 1 // Copyright GoFrame Author(https://goframe.org). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/gogf/gf. 6 7 package goai 8 9 import ( 10 "fmt" 11 "reflect" 12 13 "github.com/gogf/gf/v2/internal/json" 14 "github.com/gogf/gf/v2/text/gstr" 15 "github.com/gogf/gf/v2/util/gconv" 16 "github.com/gogf/gf/v2/util/gtag" 17 ) 18 19 type SchemaRefs []SchemaRef 20 21 type SchemaRef struct { 22 Ref string 23 Value *Schema 24 } 25 26 // isEmbeddedStructDefinition checks and returns whether given golang type is embedded struct definition, like: 27 // 28 // struct A struct{ 29 // B struct{ 30 // // ... 31 // } 32 // } 33 // 34 // The `B` in `A` is called `embedded struct definition`. 35 func (oai *OpenApiV3) isEmbeddedStructDefinition(golangType reflect.Type) bool { 36 s := golangType.String() 37 return gstr.Contains(s, `struct {`) 38 } 39 40 // newSchemaRefWithGolangType creates a new Schema and returns its SchemaRef. 41 func (oai *OpenApiV3) newSchemaRefWithGolangType(golangType reflect.Type, tagMap map[string]string) (*SchemaRef, error) { 42 var ( 43 err error 44 oaiType = oai.golangTypeToOAIType(golangType) 45 oaiFormat = oai.golangTypeToOAIFormat(golangType) 46 typeName = golangType.Name() 47 pkgPath = golangType.PkgPath() 48 schemaRef = &SchemaRef{} 49 schema = &Schema{ 50 Type: oaiType, 51 Format: oaiFormat, 52 XExtensions: make(XExtensions), 53 } 54 ) 55 if pkgPath == "" { 56 switch golangType.Kind() { 57 case reflect.Ptr, reflect.Array, reflect.Slice: 58 pkgPath = golangType.Elem().PkgPath() 59 typeName = golangType.Elem().Name() 60 } 61 } 62 63 // Type enums. 64 var typeId = fmt.Sprintf(`%s.%s`, pkgPath, typeName) 65 if enums := gtag.GetEnumsByType(typeId); enums != "" { 66 schema.Enum = make([]interface{}, 0) 67 if err = json.Unmarshal([]byte(enums), &schema.Enum); err != nil { 68 return nil, err 69 } 70 } 71 72 if len(tagMap) > 0 { 73 if err := oai.tagMapToSchema(tagMap, schema); err != nil { 74 return nil, err 75 } 76 if oaiType == TypeArray && schema.Type == TypeFile { 77 schema.Type = TypeArray 78 } 79 } 80 schemaRef.Value = schema 81 switch oaiType { 82 case TypeString, TypeFile: 83 // Nothing to do. 84 case TypeInteger: 85 if schemaRef.Value.Default != nil { 86 schemaRef.Value.Default = gconv.Int64(schemaRef.Value.Default) 87 } 88 // keep the default value as nil. 89 90 // example value needs to be converted just like default value 91 if schemaRef.Value.Example != nil { 92 schemaRef.Value.Example = gconv.Int64(schemaRef.Value.Example) 93 } 94 // keep the example value as nil. 95 case TypeNumber: 96 if schemaRef.Value.Default != nil { 97 schemaRef.Value.Default = gconv.Float64(schemaRef.Value.Default) 98 } 99 // keep the default value as nil. 100 101 // example value needs to be converted just like default value 102 if schemaRef.Value.Example != nil { 103 schemaRef.Value.Example = gconv.Float64(schemaRef.Value.Example) 104 } 105 // keep the example value as nil. 106 case TypeBoolean: 107 if schemaRef.Value.Default != nil { 108 schemaRef.Value.Default = gconv.Bool(schemaRef.Value.Default) 109 } 110 // keep the default value as nil. 111 112 // example value needs to be converted just like default value 113 if schemaRef.Value.Example != nil { 114 schemaRef.Value.Example = gconv.Bool(schemaRef.Value.Example) 115 } 116 // keep the example value as nil. 117 case TypeArray: 118 subSchemaRef, err := oai.newSchemaRefWithGolangType(golangType.Elem(), nil) 119 if err != nil { 120 return nil, err 121 } 122 schema.Items = subSchemaRef 123 if len(schema.Enum) > 0 { 124 schema.Items.Value.Enum = schema.Enum 125 schema.Enum = nil 126 } 127 128 case TypeObject: 129 for golangType.Kind() == reflect.Ptr { 130 golangType = golangType.Elem() 131 } 132 switch golangType.Kind() { 133 case reflect.Map: 134 // Specially for map type. 135 subSchemaRef, err := oai.newSchemaRefWithGolangType(golangType.Elem(), nil) 136 if err != nil { 137 return nil, err 138 } 139 schema.AdditionalProperties = subSchemaRef 140 return schemaRef, nil 141 142 case reflect.Interface: 143 // Specially for interface type. 144 var ( 145 structTypeName = oai.golangTypeToSchemaName(golangType) 146 ) 147 if oai.Components.Schemas.Get(structTypeName) == nil { 148 if err := oai.addSchema(reflect.New(golangType).Interface()); err != nil { 149 return nil, err 150 } 151 } 152 schemaRef.Ref = structTypeName 153 schemaRef.Value = nil 154 155 default: 156 golangTypeInstance := reflect.New(golangType).Elem().Interface() 157 if oai.isEmbeddedStructDefinition(golangType) { 158 schema, err = oai.structToSchema(golangTypeInstance) 159 if err != nil { 160 return nil, err 161 } 162 schemaRef.Ref = "" 163 schemaRef.Value = schema 164 } else { 165 var structTypeName = oai.golangTypeToSchemaName(golangType) 166 if oai.Components.Schemas.Get(structTypeName) == nil { 167 if err := oai.addSchema(golangTypeInstance); err != nil { 168 return nil, err 169 } 170 } 171 schemaRef.Ref = structTypeName 172 schemaRef.Value = nil 173 } 174 } 175 } 176 return schemaRef, nil 177 } 178 179 func (r SchemaRef) MarshalJSON() ([]byte, error) { 180 if r.Ref != "" { 181 return formatRefToBytes(r.Ref), nil 182 } 183 return json.Marshal(r.Value) 184 }