mirror of
https://gitee.com/johng/gf
synced 2026-06-06 02:25:47 +08:00
improve package goai; add example for array items response definition
This commit is contained in:
33
example/httpserver/response_with_json_array/controller.go
Normal file
33
example/httpserver/response_with_json_array/controller.go
Normal file
@ -0,0 +1,33 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
type Req struct {
|
||||
g.Meta `path:"/user" method:"get"`
|
||||
}
|
||||
type Res []Item
|
||||
|
||||
type Item struct {
|
||||
Id int64
|
||||
Name string
|
||||
}
|
||||
|
||||
var (
|
||||
User = cUser{}
|
||||
)
|
||||
|
||||
type cUser struct{}
|
||||
|
||||
func (c *cUser) GetList(ctx context.Context, req *Req) (res *Res, err error) {
|
||||
res = &Res{
|
||||
{Id: 1, Name: "john"},
|
||||
{Id: 2, Name: "smith"},
|
||||
{Id: 3, Name: "alice"},
|
||||
{Id: 4, Name: "katyusha"},
|
||||
}
|
||||
return
|
||||
}
|
||||
23
example/httpserver/response_with_json_array/main.go
Normal file
23
example/httpserver/response_with_json_array/main.go
Normal file
@ -0,0 +1,23 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := g.Server()
|
||||
s.Group("/", func(group *ghttp.RouterGroup) {
|
||||
group.Middleware(ghttp.MiddlewareHandlerResponse)
|
||||
group.Bind(
|
||||
User,
|
||||
)
|
||||
})
|
||||
oai := s.GetOpenApi()
|
||||
oai.Config.CommonResponse = ghttp.DefaultHandlerResponse{}
|
||||
oai.Config.CommonResponseDataField = "Data"
|
||||
s.SetOpenApiPath("/api")
|
||||
s.SetSwaggerPath("/swagger")
|
||||
s.SetPort(8199)
|
||||
s.Run()
|
||||
}
|
||||
@ -213,9 +213,9 @@ func (oai *OpenApiV3) addPath(in addPathInput) error {
|
||||
contentTypes = oai.Config.ReadContentTypes
|
||||
tagMimeValue = gmeta.Get(outputObject.Interface(), TagNameMime).String()
|
||||
refInput = getResponseSchemaRefInput{
|
||||
BusinessStructName: outputStructTypeName,
|
||||
ResponseObject: oai.Config.CommonResponse,
|
||||
ResponseDataField: oai.Config.CommonResponseDataField,
|
||||
BusinessStructName: outputStructTypeName,
|
||||
CommonResponseObject: oai.Config.CommonResponse,
|
||||
CommonResponseDataField: oai.Config.CommonResponseDataField,
|
||||
}
|
||||
)
|
||||
if tagMimeValue != "" {
|
||||
@ -224,8 +224,8 @@ func (oai *OpenApiV3) addPath(in addPathInput) error {
|
||||
for _, v := range contentTypes {
|
||||
// If customized response mime type, it then ignores common response feature.
|
||||
if tagMimeValue != "" {
|
||||
refInput.ResponseObject = nil
|
||||
refInput.ResponseDataField = ""
|
||||
refInput.CommonResponseObject = nil
|
||||
refInput.CommonResponseDataField = ""
|
||||
}
|
||||
schemaRef, err := oai.getResponseSchemaRef(refInput)
|
||||
if err != nil {
|
||||
|
||||
@ -38,33 +38,33 @@ func (r ResponseRef) MarshalJSON() ([]byte, error) {
|
||||
}
|
||||
|
||||
type getResponseSchemaRefInput struct {
|
||||
BusinessStructName string // The business struct name.
|
||||
ResponseObject interface{} // Common response object.
|
||||
ResponseDataField string // Common response data field.
|
||||
BusinessStructName string // The business struct name.
|
||||
CommonResponseObject interface{} // Common response object.
|
||||
CommonResponseDataField string // Common response data field.
|
||||
}
|
||||
|
||||
func (oai *OpenApiV3) getResponseSchemaRef(in getResponseSchemaRefInput) (*SchemaRef, error) {
|
||||
if in.ResponseObject == nil {
|
||||
if in.CommonResponseObject == nil {
|
||||
return &SchemaRef{
|
||||
Ref: in.BusinessStructName,
|
||||
}, nil
|
||||
}
|
||||
|
||||
var (
|
||||
dataFieldsPartsArray = gstr.Split(in.ResponseDataField, ".")
|
||||
dataFieldsPartsArray = gstr.Split(in.CommonResponseDataField, ".")
|
||||
bizResponseStructSchemaRef, bizResponseStructSchemaRefExist = oai.Components.Schemas[in.BusinessStructName]
|
||||
schema, err = oai.structToSchema(in.ResponseObject)
|
||||
schema, err = oai.structToSchema(in.CommonResponseObject)
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if in.ResponseDataField == "" && bizResponseStructSchemaRefExist {
|
||||
if in.CommonResponseDataField == "" && bizResponseStructSchemaRefExist {
|
||||
for k, v := range bizResponseStructSchemaRef.Value.Properties {
|
||||
schema.Properties[k] = v
|
||||
}
|
||||
} else {
|
||||
structFields, _ := gstructs.Fields(gstructs.FieldsInput{
|
||||
Pointer: in.ResponseObject,
|
||||
Pointer: in.CommonResponseObject,
|
||||
RecursiveOption: gstructs.RecursiveOptionEmbeddedNoTag,
|
||||
})
|
||||
for _, structField := range structFields {
|
||||
@ -86,9 +86,9 @@ func (oai *OpenApiV3) getResponseSchemaRef(in getResponseSchemaRefInput) (*Schem
|
||||
structFieldInstance = reflect.New(structField.Type().Type).Elem()
|
||||
)
|
||||
schemaRef, err := oai.getResponseSchemaRef(getResponseSchemaRefInput{
|
||||
BusinessStructName: in.BusinessStructName,
|
||||
ResponseObject: structFieldInstance,
|
||||
ResponseDataField: gstr.Join(dataFieldsPartsArray[1:], "."),
|
||||
BusinessStructName: in.BusinessStructName,
|
||||
CommonResponseObject: structFieldInstance,
|
||||
CommonResponseDataField: gstr.Join(dataFieldsPartsArray[1:], "."),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@ -10,6 +10,7 @@ import (
|
||||
"reflect"
|
||||
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/internal/utils"
|
||||
"github.com/gogf/gf/v2/os/gstructs"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
@ -64,6 +65,8 @@ type Discriminator struct {
|
||||
Mapping map[string]string `json:"mapping,omitempty" yaml:"mapping,omitempty"`
|
||||
}
|
||||
|
||||
// addSchema creates schemas with objects.
|
||||
// Note that the `object` can be array alias like: `type Res []Item`.
|
||||
func (oai *OpenApiV3) addSchema(object ...interface{}) error {
|
||||
for _, v := range object {
|
||||
if err := oai.doAddSchemaSingle(v); err != nil {
|
||||
@ -104,10 +107,6 @@ func (oai *OpenApiV3) doAddSchemaSingle(object interface{}) error {
|
||||
|
||||
// structToSchema converts and returns given struct object as Schema.
|
||||
func (oai *OpenApiV3) structToSchema(object interface{}) (*Schema, error) {
|
||||
structFields, _ := gstructs.Fields(gstructs.FieldsInput{
|
||||
Pointer: object,
|
||||
RecursiveOption: gstructs.RecursiveOptionEmbeddedNoTag,
|
||||
})
|
||||
var (
|
||||
tagMap = gmeta.Data(object)
|
||||
schema = &Schema{
|
||||
@ -123,6 +122,21 @@ func (oai *OpenApiV3) structToSchema(object interface{}) (*Schema, error) {
|
||||
if schema.Type != "" && schema.Type != TypeObject {
|
||||
return schema, nil
|
||||
}
|
||||
// []struct.
|
||||
if utils.IsArray(object) {
|
||||
schema.Type = TypeArray
|
||||
subSchemaRef, err := oai.newSchemaRefWithGolangType(reflect.TypeOf(object).Elem(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
schema.Items = subSchemaRef
|
||||
return schema, nil
|
||||
}
|
||||
// struct.
|
||||
structFields, _ := gstructs.Fields(gstructs.FieldsInput{
|
||||
Pointer: object,
|
||||
RecursiveOption: gstructs.RecursiveOptionEmbeddedNoTag,
|
||||
})
|
||||
schema.Type = TypeObject
|
||||
for _, structField := range structFields {
|
||||
if !gstr.IsLetterUpper(structField.Name()[0]) {
|
||||
|
||||
Reference in New Issue
Block a user