package swagger import "github.com/zeromicro/go-zero/tools/goctl/api/spec" func fillAllStructs(api *spec.ApiSpec) { var ( tps []spec.Type structTypes = make(map[string]spec.DefineStruct) groups []spec.Group ) for _, tp := range api.Types { structTypes[tp.Name()] = tp.(spec.DefineStruct) } for _, tp := range api.Types { filledTP := fillStruct("", tp, structTypes) tps = append(tps, filledTP) structTypes[filledTP.Name()] = filledTP.(spec.DefineStruct) } for _, group := range api.Service.Groups { routes := make([]spec.Route, 0, len(group.Routes)) for _, route := range group.Routes { route.RequestType = fillStruct("", route.RequestType, structTypes) route.ResponseType = fillStruct("", route.ResponseType, structTypes) routes = append(routes, route) } group.Routes = routes groups = append(groups, group) } api.Service.Groups = groups api.Types = tps } func fillStruct(parent string, tp spec.Type, allTypes map[string]spec.DefineStruct) spec.Type { switch val := tp.(type) { case spec.DefineStruct: var members []spec.Member for _, member := range val.Members { switch memberType := member.Type.(type) { case spec.PointerType: member.Type = spec.PointerType{ RawName: memberType.RawName, Type: fillStruct(val.Name(), memberType.Type, allTypes), } case spec.ArrayType: member.Type = spec.ArrayType{ RawName: memberType.RawName, Value: fillStruct(val.Name(), memberType.Value, allTypes), } case spec.MapType: member.Type = spec.MapType{ RawName: memberType.RawName, Key: memberType.Key, Value: fillStruct(val.Name(), memberType.Value, allTypes), } case spec.DefineStruct: if parent != memberType.Name() { // avoid recursive struct if st, ok := allTypes[memberType.Name()]; ok { member.Type = fillStruct("", st, allTypes) } } case spec.NestedStruct: member.Type = fillStruct("", member.Type, allTypes) } members = append(members, member) } if len(members) == 0 { st, ok := allTypes[val.RawName] if ok { members = st.Members } } val.Members = members return val case spec.NestedStruct: members := make([]spec.Member, 0, len(val.Members)) for _, member := range val.Members { switch memberType := member.Type.(type) { case spec.PointerType: member.Type = spec.PointerType{ RawName: memberType.RawName, Type: fillStruct(val.Name(), memberType.Type, allTypes), } case spec.ArrayType: member.Type = spec.ArrayType{ RawName: memberType.RawName, Value: fillStruct(val.Name(), memberType.Value, allTypes), } case spec.MapType: member.Type = spec.MapType{ RawName: memberType.RawName, Key: memberType.Key, Value: fillStruct(val.Name(), memberType.Value, allTypes), } case spec.DefineStruct: if parent != memberType.Name() { // avoid recursive struct if st, ok := allTypes[memberType.Name()]; ok { member.Type = fillStruct("", st, allTypes) } } case spec.NestedStruct: if parent != memberType.Name() { if st, ok := allTypes[memberType.Name()]; ok { member.Type = fillStruct("", st, allTypes) } } } members = append(members, member) } if len(members) == 0 { st, ok := allTypes[val.RawName] if ok { members = st.Members } } val.Members = members return val case spec.PointerType: return spec.PointerType{ RawName: val.RawName, Type: fillStruct(parent, val.Type, allTypes), } case spec.ArrayType: return spec.ArrayType{ RawName: val.RawName, Value: fillStruct(parent, val.Value, allTypes), } case spec.MapType: return spec.MapType{ RawName: val.RawName, Key: val.Key, Value: fillStruct(parent, val.Value, allTypes), } default: return tp } }